blob: f549a86583c050af3a7b3ac6372e835c27955f07 [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;
Siddharth Raybb608c82017-03-16 11:33:34 -070080import com.android.internal.location.gnssmetrics.GnssMetrics;
jackqdyulei455e90a2017-02-09 15:29:16 -080081import com.android.internal.location.GpsNetInitiatedHandler;
82import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
83import com.android.internal.location.ProviderProperties;
84import com.android.internal.location.ProviderRequest;
Siddharth Raybb608c82017-03-16 11:33:34 -070085
jackqdyulei455e90a2017-02-09 15:29:16 -080086import com.android.server.power.BatterySaverPolicy;
87import com.android.server.power.BatterySaverPolicy.ServiceType;
88
89import libcore.io.IoUtils;
90
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091import java.io.File;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070092import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093import java.io.FileInputStream;
94import java.io.IOException;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070095import java.io.PrintWriter;
destradaaea8a8a62014-06-23 18:19:03 -070096import java.net.InetAddress;
97import java.net.UnknownHostException;
Wyatt Rileycf879db2017-01-12 13:57:38 -080098import java.util.ArrayList;
Andreas Gampee6748ce2015-12-11 18:00:38 -080099import java.util.Arrays;
Mike Lockwoodf1218be2010-01-29 09:20:06 -0500100import java.util.Date;
Wyatt Rileycf879db2017-01-12 13:57:38 -0800101import java.util.List;
Danke Xie22d1f9f2009-08-18 18:28:45 -0400102import java.util.Map.Entry;
Jake Hambyb49a73d2011-03-15 20:09:46 -0700103import java.util.Properties;
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700104import java.util.Map;
105import java.util.HashMap;
Colin Cross7c030ed2014-01-28 09:33:53 -0800106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107/**
gomo4402af62017-01-11 13:20:13 -0800108 * A GNSS implementation of LocationProvider used by LocationManager.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109 *
110 * {@hide}
111 */
Lifu Tang30f95a72016-01-07 23:20:38 -0800112public class GnssLocationProvider implements LocationProviderInterface {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113
Lifu Tang30f95a72016-01-07 23:20:38 -0800114 private static final String TAG = "GnssLocationProvider";
Mike Lockwood29c84342009-05-06 14:01:15 -0400115
Brian Muramatsu1715cb32012-08-08 17:32:21 -0700116 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
117 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400118
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700119 private static final ProviderProperties PROPERTIES = new ProviderProperties(
120 true, true, false, false, true, true, true,
121 Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
122
gomo4402af62017-01-11 13:20:13 -0800123 // these need to match GnssPositionMode enum in IGnss.hal
The Android Open Source Project10592532009-03-18 17:39:46 -0700124 private static final int GPS_POSITION_MODE_STANDALONE = 0;
125 private static final int GPS_POSITION_MODE_MS_BASED = 1;
126 private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
127
gomo4402af62017-01-11 13:20:13 -0800128 // these need to match GnssPositionRecurrence enum in IGnss.hal
Mike Lockwood04598b62010-04-14 17:17:24 -0400129 private static final int GPS_POSITION_RECURRENCE_PERIODIC = 0;
130 private static final int GPS_POSITION_RECURRENCE_SINGLE = 1;
131
gomo4402af62017-01-11 13:20:13 -0800132 // these need to match GnssStatusValue enum in IGnssCallback.hal
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 private static final int GPS_STATUS_NONE = 0;
134 private static final int GPS_STATUS_SESSION_BEGIN = 1;
135 private static final int GPS_STATUS_SESSION_END = 2;
136 private static final int GPS_STATUS_ENGINE_ON = 3;
137 private static final int GPS_STATUS_ENGINE_OFF = 4;
138
gomo4402af62017-01-11 13:20:13 -0800139 // these need to match AGnssStatusValue enum in IAGnssCallback.hal
Mike Lockwoode3635c92009-05-11 08:38:02 -0400140 /** AGPS status event values. */
141 private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
142 private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
143 private static final int GPS_AGPS_DATA_CONNECTED = 3;
144 private static final int GPS_AGPS_DATA_CONN_DONE = 4;
145 private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
Mike Lockwood58bda982009-04-14 16:25:07 -0400146
gomo4402af62017-01-11 13:20:13 -0800147 // these need to match GnssLocationFlags enum in types.hal
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 private static final int LOCATION_INVALID = 0;
149 private static final int LOCATION_HAS_LAT_LONG = 1;
150 private static final int LOCATION_HAS_ALTITUDE = 2;
151 private static final int LOCATION_HAS_SPEED = 4;
152 private static final int LOCATION_HAS_BEARING = 8;
gomo4402af62017-01-11 13:20:13 -0800153 private static final int LOCATION_HAS_HORIZONTAL_ACCURACY = 16;
154 private static final int LOCATION_HAS_VERTICAL_ACCURACY = 32;
155 private static final int LOCATION_HAS_SPEED_ACCURACY = 64;
156 private static final int LOCATION_HAS_BEARING_ACCURACY = 128;
Mike Lockwoode3635c92009-05-11 08:38:02 -0400157
gomo4402af62017-01-11 13:20:13 -0800158
159 // IMPORTANT - the GPS_DELETE_* symbols here must match GnssAidingData enum in IGnss.hal
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 private static final int GPS_DELETE_EPHEMERIS = 0x0001;
161 private static final int GPS_DELETE_ALMANAC = 0x0002;
162 private static final int GPS_DELETE_POSITION = 0x0004;
163 private static final int GPS_DELETE_TIME = 0x0008;
164 private static final int GPS_DELETE_IONO = 0x0010;
165 private static final int GPS_DELETE_UTC = 0x0020;
166 private static final int GPS_DELETE_HEALTH = 0x0040;
167 private static final int GPS_DELETE_SVDIR = 0x0080;
168 private static final int GPS_DELETE_SVSTEER = 0x0100;
169 private static final int GPS_DELETE_SADATA = 0x0200;
170 private static final int GPS_DELETE_RTI = 0x0400;
171 private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
172 private static final int GPS_DELETE_ALL = 0xFFFF;
173
gomo4402af62017-01-11 13:20:13 -0800174 // The GPS_CAPABILITY_* flags must match Capabilities enum in IGnssCallback.hal
Mike Lockwood04598b62010-04-14 17:17:24 -0400175 private static final int GPS_CAPABILITY_SCHEDULING = 0x0000001;
176 private static final int GPS_CAPABILITY_MSB = 0x0000002;
177 private static final int GPS_CAPABILITY_MSA = 0x0000004;
178 private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400179 private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010;
destradaa6568d702014-10-27 12:47:41 -0700180 private static final int GPS_CAPABILITY_GEOFENCING = 0x0000020;
181 private static final int GPS_CAPABILITY_MEASUREMENTS = 0x0000040;
182 private static final int GPS_CAPABILITY_NAV_MESSAGES = 0x0000080;
Mike Lockwood04598b62010-04-14 17:17:24 -0400183
Tsuwei Chen462bcd82014-09-17 12:28:49 -0700184 // The AGPS SUPL mode
185 private static final int AGPS_SUPL_MODE_MSA = 0x02;
186 private static final int AGPS_SUPL_MODE_MSB = 0x01;
187
gomo4402af62017-01-11 13:20:13 -0800188 // these need to match AGnssType enum in IAGnssCallback.hal
Mike Lockwoode3635c92009-05-11 08:38:02 -0400189 private static final int AGPS_TYPE_SUPL = 1;
190 private static final int AGPS_TYPE_C2K = 2;
191
gomo4402af62017-01-11 13:20:13 -0800192 // these must match the ApnIpType enum in IAGnss.hal
destradaa96a14702014-06-05 11:36:30 -0700193 private static final int APN_INVALID = 0;
194 private static final int APN_IPV4 = 1;
195 private static final int APN_IPV6 = 2;
196 private static final int APN_IPV4V6 = 3;
197
Mike Lockwoode3635c92009-05-11 08:38:02 -0400198 // for mAGpsDataConnectionState
199 private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
200 private static final int AGPS_DATA_CONNECTION_OPENING = 1;
201 private static final int AGPS_DATA_CONNECTION_OPEN = 2;
Mike Lockwood58bda982009-04-14 16:25:07 -0400202
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400203 // Handler messages
204 private static final int CHECK_LOCATION = 1;
205 private static final int ENABLE = 2;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700206 private static final int SET_REQUEST = 3;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400207 private static final int UPDATE_NETWORK_STATE = 4;
208 private static final int INJECT_NTP_TIME = 5;
209 private static final int DOWNLOAD_XTRA_DATA = 6;
210 private static final int UPDATE_LOCATION = 7;
211 private static final int ADD_LISTENER = 8;
212 private static final int REMOVE_LISTENER = 9;
Kevin Tang40e1baf2012-01-10 14:32:44 -0800213 private static final int INJECT_NTP_TIME_FINISHED = 10;
214 private static final int DOWNLOAD_XTRA_DATA_FINISHED = 11;
destradaafb23c672015-04-16 14:01:27 -0700215 private static final int SUBSCRIPTION_OR_SIM_CHANGED = 12;
216 private static final int INITIALIZE_HANDLER = 13;
destradaae21252a2015-09-08 12:32:59 -0700217 private static final int REQUEST_SUPL_CONNECTION = 14;
218 private static final int RELEASE_SUPL_CONNECTION = 15;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400219
Miguel Torroja1e84da82010-07-27 07:02:24 +0200220 // Request setid
221 private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
222 private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2;
223
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700224 //TODO(b/33112647): Create gps_debug.conf with commented career parameters.
225 private static final String DEBUG_PROPERTIES_FILE = "/etc/gps_debug.conf";
Miguel Torroja1e84da82010-07-27 07:02:24 +0200226
227 // ref. location info
228 private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
229 private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
Miguel Torroja1e84da82010-07-27 07:02:24 +0200230
231 // set id info
232 private static final int AGPS_SETID_TYPE_NONE = 0;
233 private static final int AGPS_SETID_TYPE_IMSI = 1;
234 private static final int AGPS_SETID_TYPE_MSISDN = 2;
235
destradaa0682809a2013-08-12 18:50:30 -0700236 private static final int GPS_GEOFENCE_UNAVAILABLE = 1<<0L;
237 private static final int GPS_GEOFENCE_AVAILABLE = 1<<1L;
238
gomo4402af62017-01-11 13:20:13 -0800239 // GPS Geofence errors. Should match GeofenceStatus enum in IGnssGeofenceCallback.hal.
destradaa0682809a2013-08-12 18:50:30 -0700240 private static final int GPS_GEOFENCE_OPERATION_SUCCESS = 0;
241 private static final int GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES = 100;
242 private static final int GPS_GEOFENCE_ERROR_ID_EXISTS = -101;
243 private static final int GPS_GEOFENCE_ERROR_ID_UNKNOWN = -102;
244 private static final int GPS_GEOFENCE_ERROR_INVALID_TRANSITION = -103;
245 private static final int GPS_GEOFENCE_ERROR_GENERIC = -149;
246
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700247 // TCP/IP constants.
248 // Valid TCP/UDP port range is (0, 65535].
249 private static final int TCP_MIN_PORT = 0;
250 private static final int TCP_MAX_PORT = 0xffff;
251
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700252 /** simpler wrapper for ProviderRequest + Worksource */
253 private static class GpsRequest {
254 public ProviderRequest request;
255 public WorkSource source;
256 public GpsRequest(ProviderRequest request, WorkSource source) {
257 this.request = request;
258 this.source = source;
259 }
260 }
261
262 private Object mLock = new Object();
263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 // current status
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400265 private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266
267 // time for last status update
268 private long mStatusUpdateTime = SystemClock.elapsedRealtime();
Mike Lockwoodd53ba012010-04-15 20:41:26 -0400269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 // turn off GPS fix icon if we haven't received a fix in 10 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400271 private static final long RECENT_FIX_TIMEOUT = 10 * 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272
Mike Lockwood0632ca72009-05-14 15:51:03 -0400273 // stop trying if we do not receive a fix within 60 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400274 private static final int NO_FIX_TIMEOUT = 60 * 1000;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400275
Nick Pellyb041f232012-05-07 17:12:25 -0700276 // if the fix interval is below this we leave GPS on,
277 // if above then we cycle the GPS driver.
278 // Typical hot TTTF is ~5 seconds, so 10 seconds seems sane.
279 private static final int GPS_POLLING_THRESHOLD_INTERVAL = 10 * 1000;
280
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700281 // how often to request NTP time, in milliseconds
282 // current setting 24 hours
283 private static final long NTP_INTERVAL = 24*60*60*1000;
284 // how long to wait if we have a network error in NTP or XTRA downloading
Wei Liu6f6326b2015-06-24 23:47:50 -0700285 // the initial value of the exponential backoff
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700286 // current setting - 5 minutes
287 private static final long RETRY_INTERVAL = 5*60*1000;
Wei Liu6f6326b2015-06-24 23:47:50 -0700288 // how long to wait if we have a network error in NTP or XTRA downloading
289 // the max value of the exponential backoff
290 // current setting - 4 hours
291 private static final long MAX_RETRY_INTERVAL = 4*60*60*1000;
292
Wei Wangc5706f62017-04-18 11:26:26 -0700293 // Timeout when holding wakelocks for downloading XTRA data.
294 private static final long DOWNLOAD_XTRA_DATA_TIMEOUT_MS = 60 * 1000;
295
Wei Liu6f6326b2015-06-24 23:47:50 -0700296 private BackOff mNtpBackOff = new BackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL);
297 private BackOff mXtraBackOff = new BackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700298
299 // true if we are enabled, protected by this
300 private boolean mEnabled;
301
Kevin Tang40e1baf2012-01-10 14:32:44 -0800302 // states for injecting ntp and downloading xtra data
303 private static final int STATE_PENDING_NETWORK = 0;
304 private static final int STATE_DOWNLOADING = 1;
305 private static final int STATE_IDLE = 2;
306
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400307 // flags to trigger NTP or XTRA data download when network becomes available
308 // initialized to true so we do NTP and XTRA when the network comes up after booting
Kevin Tang40e1baf2012-01-10 14:32:44 -0800309 private int mInjectNtpTimePending = STATE_PENDING_NETWORK;
310 private int mDownloadXtraDataPending = STATE_PENDING_NETWORK;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400311
destradaa56b47f82015-07-24 10:56:18 -0700312 // set to true if the GPS engine requested on-demand NTP time requests
313 private boolean mOnDemandTimeInjection;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 // true if GPS is navigating
316 private boolean mNavigating;
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -0500317
318 // true if GPS engine is on
319 private boolean mEngineOn;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700320
Mike Lockwood04598b62010-04-14 17:17:24 -0400321 // requested frequency of fixes, in milliseconds
322 private int mFixInterval = 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800323
324 // true if we started navigation
325 private boolean mStarted;
326
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -0700327 // true if single shot request is in progress
328 private boolean mSingleShot;
329
Mike Lockwood04598b62010-04-14 17:17:24 -0400330 // capabilities of the GPS engine
331 private int mEngineCapabilities;
332
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -0400333 // true if XTRA is supported
334 private boolean mSupportsXtra;
335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 // for calculating time to first fix
337 private long mFixRequestTime = 0;
338 // time to first fix for most recent session
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700339 private int mTimeToFirstFix = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800340 // time we received our last fix
341 private long mLastFixTime;
342
Mike Lockwood04598b62010-04-14 17:17:24 -0400343 private int mPositionMode;
344
David Christied4edf4c2014-08-12 15:22:27 -0700345 // Current request from underlying location clients.
346 private ProviderRequest mProviderRequest = null;
347 // Current list of underlying location clients.
348 private WorkSource mWorkSource = null;
349 // True if gps should be disabled (used to support battery saver mode in settings).
350 private boolean mDisableGps = false;
351
destradaafb23c672015-04-16 14:01:27 -0700352 /**
353 * Properties loaded from PROPERTIES_FILE.
354 * It must be accessed only inside {@link #mHandler}.
355 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356 private Properties mProperties;
destradaafb23c672015-04-16 14:01:27 -0700357
Mike Lockwood734d6032009-07-28 18:30:25 -0700358 private String mSuplServerHost;
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700359 private int mSuplServerPort = TCP_MIN_PORT;
Mike Lockwood734d6032009-07-28 18:30:25 -0700360 private String mC2KServerHost;
361 private int mC2KServerPort;
Tsuwei Chen3324e952014-09-07 01:30:42 -0700362 private boolean mSuplEsEnabled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400364 private final Context mContext;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700365 private final NtpTrustedTime mNtpTime;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700366 private final ILocationManager mILocationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800367 private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
368 private Bundle mLocationExtras = new Bundle();
Lifu Tang30f95a72016-01-07 23:20:38 -0800369 private final GnssStatusListenerHelper mListenerHelper;
Lifu Tang818aa2c2016-02-01 01:52:00 -0800370 private final GnssMeasurementsProvider mGnssMeasurementsProvider;
371 private final GnssNavigationMessageProvider mGnssNavigationMessageProvider;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400372
Victoria Lease5c24fd02012-10-01 11:00:50 -0700373 // Handler for processing events
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400374 private Handler mHandler;
The Android Open Source Project10592532009-03-18 17:39:46 -0700375
destradaae21252a2015-09-08 12:32:59 -0700376 /** It must be accessed only inside {@link #mHandler}. */
Mike Lockwoode3635c92009-05-11 08:38:02 -0400377 private int mAGpsDataConnectionState;
destradaae21252a2015-09-08 12:32:59 -0700378 /** It must be accessed only inside {@link #mHandler}. */
destradaa96a14702014-06-05 11:36:30 -0700379 private InetAddress mAGpsDataConnectionIpAddr;
destradaae21252a2015-09-08 12:32:59 -0700380
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400381 private final ConnectivityManager mConnMgr;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700382 private final GpsNetInitiatedHandler mNIHandler;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400383
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400384 // Wakelocks
Lifu Tang30f95a72016-01-07 23:20:38 -0800385 private final static String WAKELOCK_KEY = "GnssLocationProvider";
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400386 private final PowerManager.WakeLock mWakeLock;
Wei Wangb71c0492017-05-01 20:24:19 -0700387 private static final String DOWNLOAD_EXTRA_WAKELOCK_KEY = "GnssLocationProviderXtraDownload";
388 private final PowerManager.WakeLock mDownloadXtraWakeLock;
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400389
Mike Lockwood29c84342009-05-06 14:01:15 -0400390 // Alarms
391 private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
Mike Lockwood0632ca72009-05-14 15:51:03 -0400392 private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700393
394 // SIM/Carrier info.
395 private final static String SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
396
Ecco Park624ac3c2016-07-18 14:08:05 -0700397 // Persist property for LPP_PROFILE
398 private final static String LPP_PROFILE = "persist.sys.gps.lpp";
399
Ecco Park624ac3c2016-07-18 14:08:05 -0700400
401
David Christied4edf4c2014-08-12 15:22:27 -0700402 private final PowerManager mPowerManager;
Mike Lockwood29c84342009-05-06 14:01:15 -0400403 private final AlarmManager mAlarmManager;
404 private final PendingIntent mWakeupIntent;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400405 private final PendingIntent mTimeoutIntent;
Mike Lockwood29c84342009-05-06 14:01:15 -0400406
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800407 private final IAppOpsService mAppOpsService;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400408 private final IBatteryStats mBatteryStats;
The Android Open Source Project10592532009-03-18 17:39:46 -0700409
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700410 // only modified on handler thread
Dianne Hackborn002a54e2013-01-10 17:34:55 -0800411 private WorkSource mClientSource = new WorkSource();
Mike Lockwoodf1218be2010-01-29 09:20:06 -0500412
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700413 private GeofenceHardwareImpl mGeofenceHardwareImpl;
Lifu Tang82f893d2016-01-21 18:15:33 -0800414 private int mYearOfHardware = 0;
415
Wyatt Riley5d5bac82016-11-01 07:05:16 -0700416 // Set lower than the current ITAR limit of 600m/s to allow this to trigger even if GPS HAL
417 // stops output right at 600m/s, depriving this of the information of a device that reaches
418 // greater than 600m/s, and higher than the speed of sound to avoid impacting most use cases.
419 private static final float ITAR_SPEED_LIMIT_METERS_PER_SECOND = 400.0F;
420 private boolean mItarSpeedLimitExceeded = false;
421
Siddharth Raybb608c82017-03-16 11:33:34 -0700422 // GNSS Metrics
423 private GnssMetrics mGnssMetrics;
424
Lifu Tang30f95a72016-01-07 23:20:38 -0800425 private final IGnssStatusProvider mGnssStatusProvider = new IGnssStatusProvider.Stub() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700426 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -0800427 public void registerGnssStatusCallback(IGnssStatusListener callback) {
428 mListenerHelper.addListener(callback);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400429 }
430
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700431 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -0800432 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
433 mListenerHelper.removeListener(callback);
destradaaea8a8a62014-06-23 18:19:03 -0700434 }
435 };
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400436
Lifu Tang30f95a72016-01-07 23:20:38 -0800437 public IGnssStatusProvider getGnssStatusProvider() {
438 return mGnssStatusProvider;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400439 }
440
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700441 public IGpsGeofenceHardware getGpsGeofenceProxy() {
442 return mGpsGeofenceBinder;
443 }
444
Lifu Tang818aa2c2016-02-01 01:52:00 -0800445 public GnssMeasurementsProvider getGnssMeasurementsProvider() {
446 return mGnssMeasurementsProvider;
destradaaea8a8a62014-06-23 18:19:03 -0700447 }
448
Lifu Tang818aa2c2016-02-01 01:52:00 -0800449 public GnssNavigationMessageProvider getGnssNavigationMessageProvider() {
450 return mGnssNavigationMessageProvider;
destradaa4b3e3932014-07-21 18:01:47 -0700451 }
452
destradaae21252a2015-09-08 12:32:59 -0700453 /**
454 * Callback used to listen for data connectivity changes.
455 */
456 private final ConnectivityManager.NetworkCallback mNetworkConnectivityCallback =
457 new ConnectivityManager.NetworkCallback() {
458 @Override
459 public void onAvailable(Network network) {
Wyatt Riley0d6e54e22016-10-05 12:03:03 -0700460 if (mInjectNtpTimePending == STATE_PENDING_NETWORK) {
461 requestUtcTime();
462 }
463 if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
Wyatt Rileyabc69ea2017-08-08 15:15:28 -0700464 if (mSupportsXtra) {
465 // Download only if supported, (prevents an unneccesary on-boot download)
466 xtraDownloadRequest();
467 }
Wyatt Riley0d6e54e22016-10-05 12:03:03 -0700468 }
Wyatt Riley41f6bce2016-12-13 10:45:29 -0800469 // Always on, notify HAL so it can get data it needs
Wyatt Rileybb9c9902016-12-07 07:16:25 -0800470 sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
destradaae21252a2015-09-08 12:32:59 -0700471 }
Kevin Tang71ad5fe2017-05-10 19:36:20 -0700472
473 @Override
474 public void onLost(Network network) {
475 sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
476 }
destradaae21252a2015-09-08 12:32:59 -0700477 };
478
479 /**
480 * Callback used to listen for availability of a requested SUPL connection.
481 * It is kept as a separate instance from {@link #mNetworkConnectivityCallback} to be able to
482 * manage the registration/un-registration lifetimes separate.
483 */
484 private final ConnectivityManager.NetworkCallback mSuplConnectivityCallback =
485 new ConnectivityManager.NetworkCallback() {
486 @Override
Wyatt Riley41f6bce2016-12-13 10:45:29 -0800487 public void onAvailable(Network network) {
488 // Specific to a change to a SUPL enabled network becoming ready
489 sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
490 }
491
492 @Override
destradaae21252a2015-09-08 12:32:59 -0700493 public void onLost(Network network) {
494 releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
495 }
destradaae21252a2015-09-08 12:32:59 -0700496 };
497
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700498 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
The Android Open Source Project10592532009-03-18 17:39:46 -0700499 @Override public void onReceive(Context context, Intent intent) {
500 String action = intent.getAction();
Tsuwei Chen48d37f92014-09-05 15:15:34 -0700501 if (DEBUG) Log.d(TAG, "receive broadcast intent, action: " + action);
destradaaee9fd342015-08-31 13:31:17 -0700502 if (action == null) {
503 return;
504 }
505
Mike Lockwood29c84342009-05-06 14:01:15 -0400506 if (action.equals(ALARM_WAKEUP)) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -0700507 startNavigating(false);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400508 } else if (action.equals(ALARM_TIMEOUT)) {
Mike Lockwood0632ca72009-05-14 15:51:03 -0400509 hibernate();
David Christied4edf4c2014-08-12 15:22:27 -0700510 } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)
Adam Lesinski87c17df2015-05-27 13:24:13 -0700511 || PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)
David Christied4edf4c2014-08-12 15:22:27 -0700512 || Intent.ACTION_SCREEN_OFF.equals(action)
513 || Intent.ACTION_SCREEN_ON.equals(action)) {
514 updateLowPowerMode();
Wink Savillea374c3d2014-11-11 11:48:04 -0800515 } else if (action.equals(SIM_STATE_CHANGED)) {
516 subscriptionOrSimChanged(context);
David Christied4edf4c2014-08-12 15:22:27 -0700517 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700518 }
Mike Lockwood29c84342009-05-06 14:01:15 -0400519 };
The Android Open Source Project10592532009-03-18 17:39:46 -0700520
Wink Savilled09c4ca2014-11-22 10:08:16 -0800521 private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
522 new OnSubscriptionsChangedListener() {
Wink Savillea374c3d2014-11-11 11:48:04 -0800523 @Override
Wink Savilled09c4ca2014-11-22 10:08:16 -0800524 public void onSubscriptionsChanged() {
destradaafb23c672015-04-16 14:01:27 -0700525 sendMessage(SUBSCRIPTION_OR_SIM_CHANGED, 0, null);
Wink Savillea374c3d2014-11-11 11:48:04 -0800526 }
527 };
528
529 private void subscriptionOrSimChanged(Context context) {
Joe Onorato0c484102016-02-01 18:04:24 -0800530 if (DEBUG) Log.d(TAG, "received SIM related action: ");
Wink Savillea374c3d2014-11-11 11:48:04 -0800531 TelephonyManager phone = (TelephonyManager)
532 mContext.getSystemService(Context.TELEPHONY_SERVICE);
Ecco Park4fa1ab72016-10-24 13:04:52 -0700533 CarrierConfigManager configManager = (CarrierConfigManager)
534 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Wink Savillea374c3d2014-11-11 11:48:04 -0800535 String mccMnc = phone.getSimOperator();
Ecco Park4fa1ab72016-10-24 13:04:52 -0700536 boolean isKeepLppProfile = false;
Wink Savillea374c3d2014-11-11 11:48:04 -0800537 if (!TextUtils.isEmpty(mccMnc)) {
Joe Onorato0c484102016-02-01 18:04:24 -0800538 if (DEBUG) Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc);
Wink Savillea374c3d2014-11-11 11:48:04 -0800539 synchronized (mLock) {
Ecco Park4fa1ab72016-10-24 13:04:52 -0700540 if (configManager != null) {
541 PersistableBundle b = configManager.getConfig();
542 isKeepLppProfile = b.getBoolean(CarrierConfigManager.KEY_PERSIST_LPP_MODE_BOOL);
543 }
544 if (isKeepLppProfile) {
545 // load current properties for the carrier
546 loadPropertiesFromResource(context, mProperties);
547 String lpp_profile = mProperties.getProperty("LPP_PROFILE");
548 // set the persist property LPP_PROFILE for the value
Ecco Park8eec7442017-08-04 16:21:59 -0700549 if (lpp_profile != null) {
550 SystemProperties.set(LPP_PROFILE, lpp_profile);
551 }
Ecco Park624ac3c2016-07-18 14:08:05 -0700552 } else {
Ecco Park4fa1ab72016-10-24 13:04:52 -0700553 // reset the persist property
554 SystemProperties.set(LPP_PROFILE, "");
Ecco Park624ac3c2016-07-18 14:08:05 -0700555 }
Wink Savillea374c3d2014-11-11 11:48:04 -0800556 reloadGpsProperties(context, mProperties);
557 mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
558 }
559 } else {
Joe Onorato0c484102016-02-01 18:04:24 -0800560 if (DEBUG) Log.d(TAG, "SIM MCC/MNC is still not available");
Wink Savillea374c3d2014-11-11 11:48:04 -0800561 }
562 }
563
David Christied4edf4c2014-08-12 15:22:27 -0700564 private void updateLowPowerMode() {
Adam Lesinski87c17df2015-05-27 13:24:13 -0700565 // Disable GPS if we are in device idle mode.
566 boolean disableGps = mPowerManager.isDeviceIdleMode();
jackqdyulei455e90a2017-02-09 15:29:16 -0800567 final PowerSaveState result =
568 mPowerManager.getPowerSaveState(ServiceType.GPS);
569 switch (result.gpsMode) {
570 case BatterySaverPolicy.GPS_MODE_DISABLED_WHEN_SCREEN_OFF:
Adam Lesinski87c17df2015-05-27 13:24:13 -0700571 // If we are in battery saver mode and the screen is off, disable GPS.
jackqdyulei455e90a2017-02-09 15:29:16 -0800572 disableGps |= result.batterySaverEnabled && !mPowerManager.isInteractive();
David Christied4edf4c2014-08-12 15:22:27 -0700573 break;
David Christied4edf4c2014-08-12 15:22:27 -0700574 }
575 if (disableGps != mDisableGps) {
576 mDisableGps = disableGps;
577 updateRequirements();
578 }
579 }
580
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800581 public static boolean isSupported() {
582 return native_is_supported();
583 }
584
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700585 interface SetCarrierProperty {
586 public boolean set(int value);
587 }
588
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700589 private void reloadGpsProperties(Context context, Properties properties) {
Joe Onorato0c484102016-02-01 18:04:24 -0800590 if (DEBUG) Log.d(TAG, "Reset GPS properties, previous size = " + properties.size());
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700591 loadPropertiesFromResource(context, properties);
Ecco Park624ac3c2016-07-18 14:08:05 -0700592
Ecco Park624ac3c2016-07-18 14:08:05 -0700593 String lpp_prof = SystemProperties.get(LPP_PROFILE);
594 if (!TextUtils.isEmpty(lpp_prof)) {
595 // override default value of this if lpp_prof is not empty
596 properties.setProperty("LPP_PROFILE", lpp_prof);
597 }
Wyatt Riley3e1cd0b2017-04-19 17:57:14 -0700598 /*
599 * Overlay carrier properties from a debug configuration file.
600 */
601 loadPropertiesFromFile(DEBUG_PROPERTIES_FILE, properties);
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700602 // TODO: we should get rid of C2K specific setting.
603 setSuplHostPort(properties.getProperty("SUPL_HOST"),
604 properties.getProperty("SUPL_PORT"));
605 mC2KServerHost = properties.getProperty("C2K_HOST");
606 String portString = properties.getProperty("C2K_PORT");
607 if (mC2KServerHost != null && portString != null) {
608 try {
609 mC2KServerPort = Integer.parseInt(portString);
610 } catch (NumberFormatException e) {
611 Log.e(TAG, "unable to parse C2K_PORT: " + portString);
612 }
613 }
destradaaef752b62015-04-17 13:10:47 -0700614 if (native_is_gnss_configuration_supported()) {
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700615 Map<String, SetCarrierProperty> map = new HashMap<String, SetCarrierProperty>() {
616 {
617 put("SUPL_VER", (val) -> native_set_supl_version(val));
618 put("SUPL_MODE", (val) -> native_set_supl_mode(val));
619 put("SUPL_ES", (val) -> native_set_supl_es(val));
620 put("LPP_PROFILE", (val) -> native_set_lpp_profile(val));
621 put("A_GLONASS_POS_PROTOCOL_SELECT", (val) -> native_set_gnss_pos_protocol_select(val));
622 put("USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL", (val) -> native_set_emergency_supl_pdn(val));
623 put("GPS_LOCK", (val) -> native_set_gps_lock(val));
624 }
625 };
626
627 for(Entry<String, SetCarrierProperty> entry : map.entrySet()) {
628 String propertyName = entry.getKey();
629 String propertyValueString = properties.getProperty(propertyName);
630 if (propertyValueString != null) {
631 try {
632 int propertyValueInt = Integer.decode(propertyValueString);
633 boolean result = entry.getValue().set(propertyValueInt);
634 if (result == false) {
635 Log.e(TAG, "Unable to set " + propertyName);
636 }
637 } catch (NumberFormatException e) {
638 Log.e(TAG, "unable to parse propertyName: " + propertyValueString);
639 }
640 }
destradaaef752b62015-04-17 13:10:47 -0700641 }
642 } else if (DEBUG) {
643 Log.d(TAG, "Skipped configuration update because GNSS configuration in GPS HAL is not"
644 + " supported");
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700645 }
Tsuwei Chen3324e952014-09-07 01:30:42 -0700646
647 // SUPL_ES configuration.
648 String suplESProperty = mProperties.getProperty("SUPL_ES");
649 if (suplESProperty != null) {
650 try {
651 mSuplEsEnabled = (Integer.parseInt(suplESProperty) == 1);
652 } catch (NumberFormatException e) {
653 Log.e(TAG, "unable to parse SUPL_ES: " + suplESProperty);
654 }
655 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700656 }
657
658 private void loadPropertiesFromResource(Context context,
659 Properties properties) {
660 String[] configValues = context.getResources().getStringArray(
661 com.android.internal.R.array.config_gpsParameters);
662 for (String item : configValues) {
Joe Onorato0c484102016-02-01 18:04:24 -0800663 if (DEBUG) Log.d(TAG, "GpsParamsResource: " + item);
Tsuwei Chen7c485bf2014-09-10 15:33:34 -0700664 // We need to support "KEY =", but not "=VALUE".
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700665 String[] split = item.split("=");
666 if (split.length == 2) {
667 properties.setProperty(split[0].trim().toUpperCase(), split[1]);
668 } else {
669 Log.w(TAG, "malformed contents: " + item);
670 }
671 }
672 }
673
674 private boolean loadPropertiesFromFile(String filename,
675 Properties properties) {
Colin Cross7c030ed2014-01-28 09:33:53 -0800676 try {
677 File file = new File(filename);
678 FileInputStream stream = null;
679 try {
680 stream = new FileInputStream(file);
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700681 properties.load(stream);
Colin Cross7c030ed2014-01-28 09:33:53 -0800682 } finally {
683 IoUtils.closeQuietly(stream);
684 }
685
Colin Cross7c030ed2014-01-28 09:33:53 -0800686 } catch (IOException e) {
Wyatt Riley3e1cd0b2017-04-19 17:57:14 -0700687 if (DEBUG) Log.d(TAG, "Could not open GPS configuration file " + filename);
Colin Cross7c030ed2014-01-28 09:33:53 -0800688 return false;
689 }
690 return true;
691 }
692
Lifu Tang30f95a72016-01-07 23:20:38 -0800693 public GnssLocationProvider(Context context, ILocationManager ilocationManager,
Victoria Lease5cd731a2012-12-19 15:04:21 -0800694 Looper looper) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800695 mContext = context;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700696 mNtpTime = NtpTrustedTime.getInstance(context);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700697 mILocationManager = ilocationManager;
Mike Lockwood63598a02010-02-24 11:52:59 -0500698
699 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400701 // Create a wake lock
David Christied4edf4c2014-08-12 15:22:27 -0700702 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
703 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700704 mWakeLock.setReferenceCounted(true);
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400705
Wei Wangb71c0492017-05-01 20:24:19 -0700706 // Create a separate wake lock for xtra downloader as it may be released due to timeout.
707 mDownloadXtraWakeLock = mPowerManager.newWakeLock(
708 PowerManager.PARTIAL_WAKE_LOCK, DOWNLOAD_EXTRA_WAKELOCK_KEY);
709 mDownloadXtraWakeLock.setReferenceCounted(true);
710
Mike Lockwood29c84342009-05-06 14:01:15 -0400711 mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
712 mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400713 mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
Mike Lockwood29c84342009-05-06 14:01:15 -0400714
Mike Lockwood58bda982009-04-14 16:25:07 -0400715 mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
716
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800717 // App ops service to keep track of who is accessing the GPS
718 mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(
719 Context.APP_OPS_SERVICE));
720
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400721 // Battery statistics service to be notified when GPS turns on or off
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700722 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
723 BatteryStats.SERVICE_NAME));
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400724
destradaafb23c672015-04-16 14:01:27 -0700725 // Construct internal handler
726 mHandler = new ProviderHandler(looper);
727
728 // Load GPS configuration and register listeners in the background:
729 // some operations, such as opening files and registering broadcast receivers, can take a
730 // relative long time, so the ctor() is kept to create objects needed by this instance,
731 // while IO initialization and registration is delegated to our internal handler
732 // this approach is just fine because events are posted to our handler anyway
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700733 mProperties = new Properties();
destradaafb23c672015-04-16 14:01:27 -0700734 sendMessage(INITIALIZE_HANDLER, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400735
Tsuwei Chen3324e952014-09-07 01:30:42 -0700736 // Create a GPS net-initiated handler.
737 mNIHandler = new GpsNetInitiatedHandler(context,
738 mNetInitiatedListener,
739 mSuplEsEnabled);
740
Lifu Tang30f95a72016-01-07 23:20:38 -0800741 mListenerHelper = new GnssStatusListenerHelper(mHandler) {
destradaa6568d702014-10-27 12:47:41 -0700742 @Override
743 protected boolean isAvailableInPlatform() {
destradaa13a60b02015-01-15 18:36:01 -0800744 return isSupported();
destradaa6568d702014-10-27 12:47:41 -0700745 }
746
747 @Override
748 protected boolean isGpsEnabled() {
749 return isEnabled();
750 }
751 };
752
Lifu Tang818aa2c2016-02-01 01:52:00 -0800753 mGnssMeasurementsProvider = new GnssMeasurementsProvider(mHandler) {
destradaa6568d702014-10-27 12:47:41 -0700754 @Override
755 public boolean isAvailableInPlatform() {
756 return native_is_measurement_supported();
757 }
758
759 @Override
760 protected boolean registerWithService() {
761 return native_start_measurement_collection();
762 }
763
764 @Override
765 protected void unregisterFromService() {
766 native_stop_measurement_collection();
767 }
768
769 @Override
770 protected boolean isGpsEnabled() {
771 return isEnabled();
772 }
773 };
774
Lifu Tang818aa2c2016-02-01 01:52:00 -0800775 mGnssNavigationMessageProvider = new GnssNavigationMessageProvider(mHandler) {
destradaa6568d702014-10-27 12:47:41 -0700776 @Override
777 protected boolean isAvailableInPlatform() {
778 return native_is_navigation_message_supported();
779 }
780
781 @Override
782 protected boolean registerWithService() {
783 return native_start_navigation_message_collection();
784 }
785
786 @Override
787 protected void unregisterFromService() {
788 native_stop_navigation_message_collection();
789 }
790
791 @Override
792 protected boolean isGpsEnabled() {
793 return isEnabled();
794 }
795 };
Siddharth Raybb608c82017-03-16 11:33:34 -0700796 mGnssMetrics = new GnssMetrics();
Siddharth Rayfff3a9d2017-06-21 15:14:44 -0700797
798 /*
799 * A cycle of native_init() and native_cleanup() is needed so that callbacks are registered
800 * after bootup even when location is disabled. This will allow Emergency SUPL to work even
801 * when location is disabled before device restart.
802 * */
803 boolean isInitialized = native_init();
804 if(!isInitialized) {
805 Log.d(TAG, "Failed to initialize at bootup");
806 } else {
807 native_cleanup();
808 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400809 }
810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800811 /**
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500812 * Returns the name of this provider.
813 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700814 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500815 public String getName() {
816 return LocationManager.GPS_PROVIDER;
817 }
818
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700819 @Override
820 public ProviderProperties getProperties() {
821 return PROPERTIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822 }
823
destradaae21252a2015-09-08 12:32:59 -0700824 private void handleUpdateNetworkState(Network network) {
825 // retrieve NetworkInfo for this UID
826 NetworkInfo info = mConnMgr.getNetworkInfo(network);
Kevin Tang71ad5fe2017-05-10 19:36:20 -0700827
828 boolean networkAvailable = false;
829 boolean isConnected = false;
830 int type = ConnectivityManager.TYPE_NONE;
831 boolean isRoaming = false;
832 String apnName = null;
833
834 if (info != null) {
835 networkAvailable = info.isAvailable() && TelephonyManager.getDefault().getDataEnabled();
836 isConnected = info.isConnected();
837 type = info.getType();
838 isRoaming = info.isRoaming();
839 apnName = info.getExtraInfo();
destradaae21252a2015-09-08 12:32:59 -0700840 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400841
Joe Onoratof5d95cb2010-01-07 21:48:32 -0500842 if (DEBUG) {
destradaae21252a2015-09-08 12:32:59 -0700843 String message = String.format(
844 "UpdateNetworkState, state=%s, connected=%s, info=%s, capabilities=%S",
845 agpsDataConnStateAsString(),
846 isConnected,
847 info,
848 mConnMgr.getNetworkCapabilities(network));
849 Log.d(TAG, message);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800850 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400851
destradaae21252a2015-09-08 12:32:59 -0700852 if (native_is_agps_ril_supported()) {
destradaae21252a2015-09-08 12:32:59 -0700853 String defaultApn = getSelectedApn();
854 if (defaultApn == null) {
855 defaultApn = "dummy-apn";
destradaaef752b62015-04-17 13:10:47 -0700856 }
destradaae21252a2015-09-08 12:32:59 -0700857
858 native_update_network_state(
859 isConnected,
Kevin Tang71ad5fe2017-05-10 19:36:20 -0700860 type,
861 isRoaming,
destradaae21252a2015-09-08 12:32:59 -0700862 networkAvailable,
Kevin Tang71ad5fe2017-05-10 19:36:20 -0700863 apnName,
destradaae21252a2015-09-08 12:32:59 -0700864 defaultApn);
865 } else if (DEBUG) {
866 Log.d(TAG, "Skipped network state update because GPS HAL AGPS-RIL is not supported");
Mike Lockwood50130bb2010-10-11 06:22:50 -0400867 }
868
destradaae21252a2015-09-08 12:32:59 -0700869 if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
870 if (isConnected) {
Stephen Li83b69712011-01-25 18:47:28 -0800871 if (apnName == null) {
destradaae21252a2015-09-08 12:32:59 -0700872 // assign a dummy value in the case of C2K as otherwise we will have a runtime
873 // exception in the following call to native_agps_data_conn_open
Stephen Li83b69712011-01-25 18:47:28 -0800874 apnName = "dummy-apn";
875 }
destradaae21252a2015-09-08 12:32:59 -0700876 int apnIpType = getApnIpType(apnName);
destradaa96a14702014-06-05 11:36:30 -0700877 setRouting();
878 if (DEBUG) {
879 String message = String.format(
880 "native_agps_data_conn_open: mAgpsApn=%s, mApnIpType=%s",
destradaae21252a2015-09-08 12:32:59 -0700881 apnName,
882 apnIpType);
destradaa96a14702014-06-05 11:36:30 -0700883 Log.d(TAG, message);
Stephen Li8efd74d2011-03-01 20:56:00 -0800884 }
destradaae21252a2015-09-08 12:32:59 -0700885 native_agps_data_conn_open(apnName, apnIpType);
Mike Lockwood03d24672009-10-08 15:45:03 -0400886 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
887 } else {
destradaae21252a2015-09-08 12:32:59 -0700888 handleReleaseSuplConnection(GPS_AGPS_DATA_CONN_FAILED);
Mike Lockwood03d24672009-10-08 15:45:03 -0400889 }
890 }
destradaae21252a2015-09-08 12:32:59 -0700891 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400892
destradaae21252a2015-09-08 12:32:59 -0700893 private void handleRequestSuplConnection(InetAddress address) {
894 if (DEBUG) {
895 String message = String.format(
896 "requestSuplConnection, state=%s, address=%s",
897 agpsDataConnStateAsString(),
898 address);
899 Log.d(TAG, message);
900 }
901
902 if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
903 return;
904 }
905 mAGpsDataConnectionIpAddr = address;
906 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
907
908 NetworkRequest.Builder requestBuilder = new NetworkRequest.Builder();
909 requestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
910 requestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
911 NetworkRequest request = requestBuilder.build();
912 mConnMgr.requestNetwork(
913 request,
Etan Cohene9aea9d2017-02-09 18:16:58 -0800914 mSuplConnectivityCallback);
destradaae21252a2015-09-08 12:32:59 -0700915 }
916
917 private void handleReleaseSuplConnection(int agpsDataConnStatus) {
918 if (DEBUG) {
919 String message = String.format(
920 "releaseSuplConnection, state=%s, status=%s",
921 agpsDataConnStateAsString(),
922 agpsDataConnStatusAsString(agpsDataConnStatus));
923 Log.d(TAG, message);
924 }
925
926 if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_CLOSED) {
927 return;
928 }
929 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
930
931 mConnMgr.unregisterNetworkCallback(mSuplConnectivityCallback);
932 switch (agpsDataConnStatus) {
933 case GPS_AGPS_DATA_CONN_FAILED:
934 native_agps_data_conn_failed();
935 break;
936 case GPS_RELEASE_AGPS_DATA_CONN:
937 native_agps_data_conn_closed();
938 break;
939 default:
940 Log.e(TAG, "Invalid status to release SUPL connection: " + agpsDataConnStatus);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400941 }
942 }
943
944 private void handleInjectNtpTime() {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800945 if (mInjectNtpTimePending == STATE_DOWNLOADING) {
946 // already downloading data
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400947 return;
948 }
destradaae21252a2015-09-08 12:32:59 -0700949 if (!isDataNetworkConnected()) {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800950 // try again when network is up
951 mInjectNtpTimePending = STATE_PENDING_NETWORK;
952 return;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700953 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800954 mInjectNtpTimePending = STATE_DOWNLOADING;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700955
Jeff Brown028872f2012-08-25 13:07:01 -0700956 // hold wake lock while task runs
957 mWakeLock.acquire();
Lifu Tangcbd2a142016-06-22 10:57:55 -0700958 Log.i(TAG, "WakeLock acquired by handleInjectNtpTime()");
Kevin Tang40e1baf2012-01-10 14:32:44 -0800959 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
960 @Override
961 public void run() {
962 long delay;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400963
Kevin Tang40e1baf2012-01-10 14:32:44 -0800964 // force refresh NTP cache when outdated
destradaa56b47f82015-07-24 10:56:18 -0700965 boolean refreshSuccess = true;
Kevin Tang40e1baf2012-01-10 14:32:44 -0800966 if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
destradaa56b47f82015-07-24 10:56:18 -0700967 refreshSuccess = mNtpTime.forceRefresh();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800968 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400969
Kevin Tang40e1baf2012-01-10 14:32:44 -0800970 // only update when NTP time is fresh
971 if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
972 long time = mNtpTime.getCachedNtpTime();
973 long timeReference = mNtpTime.getCachedNtpTimeReference();
974 long certainty = mNtpTime.getCacheCertainty();
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400975
Joe Onorato0c484102016-02-01 18:04:24 -0800976 if (DEBUG) {
Yipeng Cao276278d2017-05-18 13:27:30 -0700977 long now = System.currentTimeMillis();
Joe Onorato0c484102016-02-01 18:04:24 -0800978 Log.d(TAG, "NTP server returned: "
979 + time + " (" + new Date(time)
980 + ") reference: " + timeReference
981 + " certainty: " + certainty
982 + " system time offset: " + (time - now));
983 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800984
985 native_inject_time(time, timeReference, (int) certainty);
986 delay = NTP_INTERVAL;
Wei Liu6f6326b2015-06-24 23:47:50 -0700987 mNtpBackOff.reset();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800988 } else {
destradaa56b47f82015-07-24 10:56:18 -0700989 Log.e(TAG, "requestTime failed");
Wei Liu6f6326b2015-06-24 23:47:50 -0700990 delay = mNtpBackOff.nextBackoffMillis();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800991 }
992
Jeff Brown028872f2012-08-25 13:07:01 -0700993 sendMessage(INJECT_NTP_TIME_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800994
destradaa56b47f82015-07-24 10:56:18 -0700995 if (DEBUG) {
996 String message = String.format(
997 "onDemandTimeInjection=%s, refreshSuccess=%s, delay=%s",
998 mOnDemandTimeInjection,
999 refreshSuccess,
1000 delay);
1001 Log.d(TAG, message);
1002 }
1003 if (mOnDemandTimeInjection || !refreshSuccess) {
Kevin Tang40e1baf2012-01-10 14:32:44 -08001004 // send delayed message for next NTP injection
1005 // since this is delayed and not urgent we do not hold a wake lock here
Jeff Brown028872f2012-08-25 13:07:01 -07001006 mHandler.sendEmptyMessageDelayed(INJECT_NTP_TIME, delay);
Kevin Tang40e1baf2012-01-10 14:32:44 -08001007 }
Jeff Brown028872f2012-08-25 13:07:01 -07001008
1009 // release wake lock held by task
1010 mWakeLock.release();
Lifu Tangcbd2a142016-06-22 10:57:55 -07001011 Log.i(TAG, "WakeLock released by handleInjectNtpTime()");
Kevin Tang40e1baf2012-01-10 14:32:44 -08001012 }
1013 });
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001014 }
1015
1016 private void handleDownloadXtraData() {
Wyatt Riley0d6e54e22016-10-05 12:03:03 -07001017 if (!mSupportsXtra) {
1018 // native code reports xtra not supported, don't try
1019 Log.d(TAG, "handleDownloadXtraData() called when Xtra not supported");
1020 return;
1021 }
Kevin Tang40e1baf2012-01-10 14:32:44 -08001022 if (mDownloadXtraDataPending == STATE_DOWNLOADING) {
1023 // already downloading data
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001024 return;
1025 }
destradaae21252a2015-09-08 12:32:59 -07001026 if (!isDataNetworkConnected()) {
Kevin Tang40e1baf2012-01-10 14:32:44 -08001027 // try again when network is up
1028 mDownloadXtraDataPending = STATE_PENDING_NETWORK;
1029 return;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001030 }
Kevin Tang40e1baf2012-01-10 14:32:44 -08001031 mDownloadXtraDataPending = STATE_DOWNLOADING;
1032
Jeff Brown028872f2012-08-25 13:07:01 -07001033 // hold wake lock while task runs
Wei Wangb71c0492017-05-01 20:24:19 -07001034 mDownloadXtraWakeLock.acquire(DOWNLOAD_XTRA_DATA_TIMEOUT_MS);
Lifu Tangcbd2a142016-06-22 10:57:55 -07001035 Log.i(TAG, "WakeLock acquired by handleDownloadXtraData()");
Kevin Tang40e1baf2012-01-10 14:32:44 -08001036 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
1037 @Override
1038 public void run() {
Andreas Gampedfdc6ac2014-10-28 20:42:53 -07001039 GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mProperties);
Kevin Tang40e1baf2012-01-10 14:32:44 -08001040 byte[] data = xtraDownloader.downloadXtraData();
1041 if (data != null) {
destradaae21252a2015-09-08 12:32:59 -07001042 if (DEBUG) Log.d(TAG, "calling native_inject_xtra_data");
Kevin Tang40e1baf2012-01-10 14:32:44 -08001043 native_inject_xtra_data(data, data.length);
Wei Liu6f6326b2015-06-24 23:47:50 -07001044 mXtraBackOff.reset();
Kevin Tang40e1baf2012-01-10 14:32:44 -08001045 }
1046
Jeff Brown028872f2012-08-25 13:07:01 -07001047 sendMessage(DOWNLOAD_XTRA_DATA_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -08001048
1049 if (data == null) {
1050 // try again later
1051 // since this is delayed and not urgent we do not hold a wake lock here
Wei Liu6f6326b2015-06-24 23:47:50 -07001052 mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA,
1053 mXtraBackOff.nextBackoffMillis());
Kevin Tang40e1baf2012-01-10 14:32:44 -08001054 }
Kevin Tang40e1baf2012-01-10 14:32:44 -08001055
Wei Wangb71c0492017-05-01 20:24:19 -07001056 // Release wake lock held by task, synchronize on mLock in case multiple
1057 // download tasks overrun.
1058 synchronized (mLock) {
1059 if (mDownloadXtraWakeLock.isHeld()) {
Zheng Zhang3cceb252017-08-07 13:51:23 -07001060 // This wakelock may have time-out, if a timeout was specified.
1061 // Catch (and ignore) any timeout exceptions.
1062 try {
1063 mDownloadXtraWakeLock.release();
1064 if (DEBUG) Log.d(TAG, "WakeLock released by handleDownloadXtraData()");
1065 } catch (Exception e) {
1066 Log.i(TAG, "Wakelock timeout & release race exception in "
1067 + "handleDownloadXtraData()", e);
1068 }
Wei Wangb71c0492017-05-01 20:24:19 -07001069 } else {
1070 Log.e(TAG, "WakeLock expired before release in "
1071 + "handleDownloadXtraData()");
1072 }
Wei Wangc5706f62017-04-18 11:26:26 -07001073 }
Jeff Brown028872f2012-08-25 13:07:01 -07001074 }
Kevin Tang40e1baf2012-01-10 14:32:44 -08001075 });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001076 }
1077
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001078 private void handleUpdateLocation(Location location) {
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -04001079 if (location.hasAccuracy()) {
1080 native_inject_location(location.getLatitude(), location.getLongitude(),
1081 location.getAccuracy());
1082 }
Mike Lockwoodfd6e5f02009-05-21 11:28:20 -04001083 }
1084
1085 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001086 * Enables this provider. When enabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -07001087 * must be handled. Hardware may be started up
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 * when the provider is enabled.
1089 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001090 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001091 public void enable() {
Laurent Tu7b5aeca2013-01-24 15:10:24 -08001092 synchronized (mLock) {
1093 if (mEnabled) return;
1094 mEnabled = true;
1095 }
1096
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001097 sendMessage(ENABLE, 1, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001098 }
1099
Tsuwei Chen52617bb2014-08-25 11:49:11 -07001100 private void setSuplHostPort(String hostString, String portString) {
1101 if (hostString != null) {
1102 mSuplServerHost = hostString;
1103 }
1104 if (portString != null) {
1105 try {
1106 mSuplServerPort = Integer.parseInt(portString);
1107 } catch (NumberFormatException e) {
1108 Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
1109 }
1110 }
Tsuwei Chen678c13c2014-09-22 17:48:41 -07001111 if (mSuplServerHost != null
1112 && mSuplServerPort > TCP_MIN_PORT
1113 && mSuplServerPort <= TCP_MAX_PORT) {
1114 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
1115 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -07001116 }
1117
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001118 /**
1119 * Checks what SUPL mode to use, according to the AGPS mode as well as the
1120 * allowed mode from properties.
1121 *
1122 * @param properties GPS properties
1123 * @param agpsEnabled whether AGPS is enabled by settings value
1124 * @param singleShot whether "singleshot" is needed
1125 * @return SUPL mode (MSA vs MSB vs STANDALONE)
1126 */
1127 private int getSuplMode(Properties properties, boolean agpsEnabled, boolean singleShot) {
1128 if (agpsEnabled) {
1129 String modeString = properties.getProperty("SUPL_MODE");
1130 int suplMode = 0;
1131 if (!TextUtils.isEmpty(modeString)) {
1132 try {
1133 suplMode = Integer.parseInt(modeString);
1134 } catch (NumberFormatException e) {
1135 Log.e(TAG, "unable to parse SUPL_MODE: " + modeString);
1136 return GPS_POSITION_MODE_STANDALONE;
1137 }
1138 }
destradaabfb3bdb2015-04-29 14:42:35 -07001139 // MS-Based is the preferred mode for Assisted-GPS position computation, so we favor
1140 // such mode when it is available
1141 if (hasCapability(GPS_CAPABILITY_MSB) && (suplMode & AGPS_SUPL_MODE_MSB) != 0) {
1142 return GPS_POSITION_MODE_MS_BASED;
1143 }
1144 // for now, just as the legacy code did, we fallback to MS-Assisted if it is available,
1145 // do fallback only for single-shot requests, because it is too expensive to do for
1146 // periodic requests as well
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001147 if (singleShot
1148 && hasCapability(GPS_CAPABILITY_MSA)
1149 && (suplMode & AGPS_SUPL_MODE_MSA) != 0) {
1150 return GPS_POSITION_MODE_MS_ASSISTED;
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001151 }
1152 }
1153 return GPS_POSITION_MODE_STANDALONE;
1154 }
1155
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001156 private void handleEnable() {
1157 if (DEBUG) Log.d(TAG, "handleEnable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001158
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001159 boolean enabled = native_init();
1160
1161 if (enabled) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04001162 mSupportsXtra = native_supports_xtra();
Tsuwei Chen678c13c2014-09-22 17:48:41 -07001163
1164 // TODO: remove the following native calls if we can make sure they are redundant.
Mike Lockwood734d6032009-07-28 18:30:25 -07001165 if (mSuplServerHost != null) {
1166 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
1167 }
1168 if (mC2KServerHost != null) {
1169 native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
1170 }
destradaa13a60b02015-01-15 18:36:01 -08001171
Lifu Tang818aa2c2016-02-01 01:52:00 -08001172 mGnssMeasurementsProvider.onGpsEnabledChanged();
1173 mGnssNavigationMessageProvider.onGpsEnabledChanged();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001174 enableBatching();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001176 synchronized (mLock) {
1177 mEnabled = false;
1178 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001179 Log.w(TAG, "Failed to enable location provider");
1180 }
1181 }
1182
1183 /**
1184 * Disables this provider. When disabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -07001185 * need not be handled. Hardware may be shut
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001186 * down while the provider is disabled.
1187 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001188 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001189 public void disable() {
Laurent Tu7b5aeca2013-01-24 15:10:24 -08001190 synchronized (mLock) {
1191 if (!mEnabled) return;
1192 mEnabled = false;
1193 }
1194
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001195 sendMessage(ENABLE, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001196 }
1197
1198 private void handleDisable() {
Mike Lockwood89096312010-03-24 10:14:55 -04001199 if (DEBUG) Log.d(TAG, "handleDisable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001200
David Christie3bc26142013-12-19 14:53:44 -08001201 updateClientUids(new WorkSource());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001202 stopNavigating();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001203 mAlarmManager.cancel(mWakeupIntent);
1204 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205
Wyatt Rileycf879db2017-01-12 13:57:38 -08001206 disableBatching();
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001207 // do this before releasing wakelock
1208 native_cleanup();
destradaa13a60b02015-01-15 18:36:01 -08001209
Lifu Tang818aa2c2016-02-01 01:52:00 -08001210 mGnssMeasurementsProvider.onGpsEnabledChanged();
1211 mGnssNavigationMessageProvider.onGpsEnabledChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212 }
1213
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001214 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001215 public boolean isEnabled() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001216 synchronized (mLock) {
1217 return mEnabled;
1218 }
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001219 }
1220
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001221 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001222 public int getStatus(Bundle extras) {
Wyatt Rileyc9f25dd2017-05-05 13:45:23 -07001223 setLocationExtras(extras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001224 return mStatus;
1225 }
1226
Wyatt Rileyc9f25dd2017-05-05 13:45:23 -07001227 private void updateStatus(int status, int svCount, int meanCn0, int maxCn0) {
1228 if (status != mStatus || svCount != mSvCount || meanCn0 != mMeanCn0 || maxCn0 != mMaxCn0 ) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001229 mStatus = status;
1230 mSvCount = svCount;
Wyatt Rileyc9f25dd2017-05-05 13:45:23 -07001231 mMeanCn0 = meanCn0;
1232 mMaxCn0 = maxCn0;
1233 setLocationExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001234 mStatusUpdateTime = SystemClock.elapsedRealtime();
1235 }
1236 }
1237
Wyatt Rileyc9f25dd2017-05-05 13:45:23 -07001238 private void setLocationExtras(Bundle extras) {
1239 if (extras != null) {
1240 extras.putInt("satellites", mSvCount);
1241 extras.putInt("meanCn0", mMeanCn0);
1242 extras.putInt("maxCn0", mMaxCn0);
1243 }
1244 }
1245
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001246 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001247 public long getStatusUpdateTime() {
1248 return mStatusUpdateTime;
1249 }
1250
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001251 @Override
1252 public void setRequest(ProviderRequest request, WorkSource source) {
1253 sendMessage(SET_REQUEST, 0, new GpsRequest(request, source));
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001254 }
1255
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001256 private void handleSetRequest(ProviderRequest request, WorkSource source) {
David Christied4edf4c2014-08-12 15:22:27 -07001257 mProviderRequest = request;
1258 mWorkSource = source;
1259 updateRequirements();
1260 }
1261
1262 // Called when the requirements for GPS may have changed
1263 private void updateRequirements() {
1264 if (mProviderRequest == null || mWorkSource == null) {
1265 return;
1266 }
1267
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001268 boolean singleShot = false;
1269
1270 // see if the request is for a single update
David Christied4edf4c2014-08-12 15:22:27 -07001271 if (mProviderRequest.locationRequests != null
1272 && mProviderRequest.locationRequests.size() > 0) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001273 // if any request has zero or more than one updates
1274 // requested, then this is not single-shot mode
1275 singleShot = true;
1276
David Christied4edf4c2014-08-12 15:22:27 -07001277 for (LocationRequest lr : mProviderRequest.locationRequests) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001278 if (lr.getNumUpdates() != 1) {
1279 singleShot = false;
1280 }
1281 }
1282 }
1283
David Christied4edf4c2014-08-12 15:22:27 -07001284 if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest);
Dante Russo260d6672016-06-20 11:11:59 -07001285 if (mProviderRequest.reportLocation && !mDisableGps && isEnabled()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001286 // update client uids
David Christied4edf4c2014-08-12 15:22:27 -07001287 updateClientUids(mWorkSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001288
David Christied4edf4c2014-08-12 15:22:27 -07001289 mFixInterval = (int) mProviderRequest.interval;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001290
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001291 // check for overflow
David Christied4edf4c2014-08-12 15:22:27 -07001292 if (mFixInterval != mProviderRequest.interval) {
1293 Log.w(TAG, "interval overflow: " + mProviderRequest.interval);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001294 mFixInterval = Integer.MAX_VALUE;
1295 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001296
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001297 // apply request to GPS engine
Mike Lockwood04598b62010-04-14 17:17:24 -04001298 if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001299 // change period
Mike Lockwood04598b62010-04-14 17:17:24 -04001300 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
1301 mFixInterval, 0, 0)) {
1302 Log.e(TAG, "set_position_mode failed in setMinTime()");
1303 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001304 } else if (!mStarted) {
1305 // start GPS
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001306 startNavigating(singleShot);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001307 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001308 } else {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001309 updateClientUids(new WorkSource());
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001310
1311 stopNavigating();
1312 mAlarmManager.cancel(mWakeupIntent);
1313 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001314 }
1315 }
1316
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001317 private void updateClientUids(WorkSource source) {
1318 // Update work source.
1319 WorkSource[] changes = mClientSource.setReturningDiffs(source);
Victoria Leaseea78b852013-01-15 10:39:28 -08001320 if (changes == null) {
1321 return;
1322 }
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001323 WorkSource newWork = changes[0];
1324 WorkSource goneWork = changes[1];
1325
1326 // Update sources that were not previously tracked.
1327 if (newWork != null) {
1328 int lastuid = -1;
1329 for (int i=0; i<newWork.size(); i++) {
Dianne Hackborn2e418422009-06-22 20:00:17 -07001330 try {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001331 int uid = newWork.get(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001332 mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService),
1333 AppOpsManager.OP_GPS, uid, newWork.getName(i));
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001334 if (uid != lastuid) {
1335 lastuid = uid;
1336 mBatteryStats.noteStartGps(uid);
1337 }
Dianne Hackborn2e418422009-06-22 20:00:17 -07001338 } catch (RemoteException e) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001339 Log.w(TAG, "RemoteException", e);
1340 }
1341 }
1342 }
1343
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001344 // Update sources that are no longer tracked.
1345 if (goneWork != null) {
1346 int lastuid = -1;
1347 for (int i=0; i<goneWork.size(); i++) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001348 try {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001349 int uid = goneWork.get(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001350 mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService),
1351 AppOpsManager.OP_GPS, uid, goneWork.getName(i));
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001352 if (uid != lastuid) {
1353 lastuid = uid;
1354 mBatteryStats.noteStopGps(uid);
1355 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001356 } catch (RemoteException e) {
1357 Log.w(TAG, "RemoteException", e);
Dianne Hackborn2e418422009-06-22 20:00:17 -07001358 }
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001359 }
1360 }
1361 }
1362
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001363 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001364 public boolean sendExtraCommand(String command, Bundle extras) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001365
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001366 long identity = Binder.clearCallingIdentity();
1367 boolean result = false;
1368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 if ("delete_aiding_data".equals(command)) {
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001370 result = deleteAidingData(extras);
1371 } else if ("force_time_injection".equals(command)) {
destradaae21252a2015-09-08 12:32:59 -07001372 requestUtcTime();
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001373 result = true;
1374 } else if ("force_xtra_injection".equals(command)) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04001375 if (mSupportsXtra) {
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001376 xtraDownloadRequest();
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001377 result = true;
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001378 }
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001379 } else {
1380 Log.w(TAG, "sendExtraCommand: unknown command " + command);
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001381 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001382
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001383 Binder.restoreCallingIdentity(identity);
1384 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385 }
1386
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001387 private IGpsGeofenceHardware mGpsGeofenceBinder = new IGpsGeofenceHardware.Stub() {
1388 public boolean isHardwareGeofenceSupported() {
1389 return native_is_geofence_supported();
1390 }
1391
1392 public boolean addCircularHardwareGeofence(int geofenceId, double latitude,
1393 double longitude, double radius, int lastTransition, int monitorTransitions,
1394 int notificationResponsiveness, int unknownTimer) {
1395 return native_add_geofence(geofenceId, latitude, longitude, radius,
1396 lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer);
1397 }
1398
1399 public boolean removeHardwareGeofence(int geofenceId) {
1400 return native_remove_geofence(geofenceId);
1401 }
1402
1403 public boolean pauseHardwareGeofence(int geofenceId) {
1404 return native_pause_geofence(geofenceId);
1405 }
1406
1407 public boolean resumeHardwareGeofence(int geofenceId, int monitorTransition) {
1408 return native_resume_geofence(geofenceId, monitorTransition);
1409 }
1410 };
1411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001412 private boolean deleteAidingData(Bundle extras) {
1413 int flags;
1414
1415 if (extras == null) {
1416 flags = GPS_DELETE_ALL;
1417 } else {
1418 flags = 0;
1419 if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
1420 if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
1421 if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
1422 if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
1423 if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
1424 if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
1425 if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
1426 if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
1427 if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
1428 if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
1429 if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
1430 if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
1431 if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
1432 }
1433
1434 if (flags != 0) {
1435 native_delete_aiding_data(flags);
1436 return true;
1437 }
1438
1439 return false;
1440 }
1441
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001442 private void startNavigating(boolean singleShot) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 if (!mStarted) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001444 if (DEBUG) Log.d(TAG, "startNavigating, singleShot is " + singleShot);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001445 mTimeToFirstFix = 0;
1446 mLastFixTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001447 mStarted = true;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001448 mSingleShot = singleShot;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001449 mPositionMode = GPS_POSITION_MODE_STANDALONE;
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001450 // Notify about suppressed output, if speed limit was previously exceeded.
1451 // Elsewhere, we check again with every speed output reported.
1452 if (mItarSpeedLimitExceeded) {
1453 Log.i(TAG, "startNavigating with ITAR limit in place. Output limited " +
1454 "until slow enough speed reported.");
1455 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001456
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001457 boolean agpsEnabled =
1458 (Settings.Global.getInt(mContext.getContentResolver(),
1459 Settings.Global.ASSISTED_GPS_ENABLED, 1) != 0);
1460 mPositionMode = getSuplMode(mProperties, agpsEnabled, singleShot);
Mike Lockwoodbcab8df2009-06-25 16:39:09 -04001461
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001462 if (DEBUG) {
1463 String mode;
1464
1465 switch(mPositionMode) {
1466 case GPS_POSITION_MODE_STANDALONE:
1467 mode = "standalone";
1468 break;
1469 case GPS_POSITION_MODE_MS_ASSISTED:
1470 mode = "MS_ASSISTED";
1471 break;
1472 case GPS_POSITION_MODE_MS_BASED:
1473 mode = "MS_BASED";
1474 break;
1475 default:
1476 mode = "unknown";
1477 break;
1478 }
1479 Log.d(TAG, "setting position_mode to " + mode);
1480 }
1481
Mike Lockwood04598b62010-04-14 17:17:24 -04001482 int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
1483 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
1484 interval, 0, 0)) {
1485 mStarted = false;
1486 Log.e(TAG, "set_position_mode failed in startNavigating()");
1487 return;
1488 }
1489 if (!native_start()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 mStarted = false;
1491 Log.e(TAG, "native_start failed in startNavigating()");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001492 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 }
1494
1495 // reset SV count to zero
Wyatt Rileyc9f25dd2017-05-05 13:45:23 -07001496 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0, 0, 0);
Yipeng Cao282b5942017-05-17 20:31:39 -07001497 mFixRequestTime = SystemClock.elapsedRealtime();
Mike Lockwood04598b62010-04-14 17:17:24 -04001498 if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
1499 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
1500 // and our fix interval is not short
1501 if (mFixInterval >= NO_FIX_TIMEOUT) {
1502 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1503 SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
1504 }
Mike Lockwood0632ca72009-05-14 15:51:03 -04001505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 }
1507 }
1508
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001509 private void stopNavigating() {
Mike Lockwood29c84342009-05-06 14:01:15 -04001510 if (DEBUG) Log.d(TAG, "stopNavigating");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 if (mStarted) {
1512 mStarted = false;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001513 mSingleShot = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001514 native_stop();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001515 mTimeToFirstFix = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 mLastFixTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517
1518 // reset SV count to zero
Wyatt Rileyc9f25dd2017-05-05 13:45:23 -07001519 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0, 0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001520 }
1521 }
1522
Mike Lockwood0632ca72009-05-14 15:51:03 -04001523 private void hibernate() {
1524 // stop GPS until our next fix interval arrives
1525 stopNavigating();
Mike Lockwood0632ca72009-05-14 15:51:03 -04001526 mAlarmManager.cancel(mTimeoutIntent);
1527 mAlarmManager.cancel(mWakeupIntent);
1528 long now = SystemClock.elapsedRealtime();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001529 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, mWakeupIntent);
Mike Lockwood04598b62010-04-14 17:17:24 -04001530 }
1531
1532 private boolean hasCapability(int capability) {
1533 return ((mEngineCapabilities & capability) != 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -04001534 }
1535
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 /**
1538 * called from native code to update our position.
1539 */
Wyatt Riley5d229832017-02-10 17:06:00 -08001540 private void reportLocation(boolean hasLatLong, Location location) {
1541 if (location.hasSpeed()) {
1542 mItarSpeedLimitExceeded = location.getSpeed() > ITAR_SPEED_LIMIT_METERS_PER_SECOND;
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001543 }
1544
1545 if (mItarSpeedLimitExceeded) {
1546 Log.i(TAG, "Hal reported a speed in excess of ITAR limit." +
1547 " GPS/GNSS Navigation output blocked.");
Siddharth Raybb608c82017-03-16 11:33:34 -07001548 mGnssMetrics.logReceivedLocationStatus(false);
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001549 return; // No output of location allowed
1550 }
1551
Wyatt Riley5d229832017-02-10 17:06:00 -08001552 if (VERBOSE) Log.v(TAG, "reportLocation " + location.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 synchronized (mLocation) {
Wyatt Riley5d229832017-02-10 17:06:00 -08001555 mLocation = location;
1556 // It would be nice to push the elapsed real-time timestamp
1557 // further down the stack, but this is still useful
1558 mLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
Sean Barbeauced2b2c2011-12-19 04:43:07 -05001559 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001561 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001562 mILocationManager.reportLocation(mLocation, false);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001563 } catch (RemoteException e) {
1564 Log.e(TAG, "RemoteException calling reportLocation");
1565 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001566 }
1567
Siddharth Raybb608c82017-03-16 11:33:34 -07001568 mGnssMetrics.logReceivedLocationStatus(hasLatLong);
1569 if (hasLatLong) {
1570 if (location.hasAccuracy()) {
1571 mGnssMetrics.logPositionAccuracyMeters(location.getAccuracy());
1572 }
1573 if (mTimeToFirstFix > 0) {
Yipeng Cao282b5942017-05-17 20:31:39 -07001574 int timeBetweenFixes = (int) (SystemClock.elapsedRealtime() - mLastFixTime);
Siddharth Raybb608c82017-03-16 11:33:34 -07001575 mGnssMetrics.logMissedReports(mFixInterval, timeBetweenFixes);
1576 }
1577 }
1578
Yipeng Cao282b5942017-05-17 20:31:39 -07001579 mLastFixTime = SystemClock.elapsedRealtime();
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001580 // report time to first fix
Wyatt Riley5d229832017-02-10 17:06:00 -08001581 if (mTimeToFirstFix == 0 && hasLatLong) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001582 mTimeToFirstFix = (int)(mLastFixTime - mFixRequestTime);
1583 if (DEBUG) Log.d(TAG, "TTFF: " + mTimeToFirstFix);
Siddharth Raybb608c82017-03-16 11:33:34 -07001584 mGnssMetrics.logTimeToFirstFixMilliSecs(mTimeToFirstFix);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001585
1586 // notify status listeners
destradaaea8a8a62014-06-23 18:19:03 -07001587 mListenerHelper.onFirstFix(mTimeToFirstFix);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001588 }
1589
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001590 if (mSingleShot) {
1591 stopNavigating();
1592 }
1593
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001594 if (mStarted && mStatus != LocationProvider.AVAILABLE) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001595 // we want to time out if we do not receive a fix
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001596 // within the time out and we are requesting infrequent fixes
Mike Lockwood04598b62010-04-14 17:17:24 -04001597 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001598 mAlarmManager.cancel(mTimeoutIntent);
1599 }
1600
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 // send an intent to notify that the GPS is receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001602 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1603 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001604 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Wyatt Rileyc9f25dd2017-05-05 13:45:23 -07001605 updateStatus(LocationProvider.AVAILABLE, mSvCount, mMeanCn0, mMaxCn0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 }
Mike Lockwood29c84342009-05-06 14:01:15 -04001607
Nick Pellyb041f232012-05-07 17:12:25 -07001608 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted &&
1609 mFixInterval > GPS_POLLING_THRESHOLD_INTERVAL) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001610 if (DEBUG) Log.d(TAG, "got fix, hibernating");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001611 hibernate();
Mike Lockwood29c84342009-05-06 14:01:15 -04001612 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 }
1614
1615 /**
1616 * called from native code to update our status
1617 */
1618 private void reportStatus(int status) {
Mike Lockwoodb8d90332010-10-18 17:59:48 -04001619 if (DEBUG) Log.v(TAG, "reportStatus status: " + status);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001620
destradaaea8a8a62014-06-23 18:19:03 -07001621 boolean wasNavigating = mNavigating;
1622 switch (status) {
1623 case GPS_STATUS_SESSION_BEGIN:
1624 mNavigating = true;
1625 mEngineOn = true;
1626 break;
1627 case GPS_STATUS_SESSION_END:
1628 mNavigating = false;
1629 break;
1630 case GPS_STATUS_ENGINE_ON:
1631 mEngineOn = true;
1632 break;
1633 case GPS_STATUS_ENGINE_OFF:
1634 mEngineOn = false;
1635 mNavigating = false;
1636 break;
1637 }
Mike Lockwooddbd6fd82009-12-07 18:43:36 -05001638
destradaaea8a8a62014-06-23 18:19:03 -07001639 if (wasNavigating != mNavigating) {
destradaa13a60b02015-01-15 18:36:01 -08001640 mListenerHelper.onStatusChanged(mNavigating);
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001641
destradaaea8a8a62014-06-23 18:19:03 -07001642 // send an intent to notify that the GPS has been enabled or disabled
1643 Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
1644 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
1645 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 }
1647 }
1648
1649 /**
1650 * called from native code to update SV info
1651 */
1652 private void reportSvStatus() {
gomo4402af62017-01-11 13:20:13 -08001653 int svCount = native_read_sv_status(mSvidWithFlags,
1654 mCn0s,
1655 mSvElevations,
1656 mSvAzimuths,
1657 mSvCarrierFreqs);
destradaaea8a8a62014-06-23 18:19:03 -07001658 mListenerHelper.onSvStatusChanged(
1659 svCount,
Lifu Tang120480f2016-02-07 18:08:19 -08001660 mSvidWithFlags,
Lifu Tang76a620f2016-02-26 19:53:01 -08001661 mCn0s,
destradaaea8a8a62014-06-23 18:19:03 -07001662 mSvElevations,
gomo4402af62017-01-11 13:20:13 -08001663 mSvAzimuths,
1664 mSvCarrierFreqs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001665
Siddharth Ray168f12a2017-07-10 11:55:10 -07001666 // Log CN0 as part of GNSS metrics
1667 mGnssMetrics.logCn0(mCn0s, svCount);
1668
Mike Lockwood29c84342009-05-06 14:01:15 -04001669 if (VERBOSE) {
Lifu Tang30f95a72016-01-07 23:20:38 -08001670 Log.v(TAG, "SV count: " + svCount);
1671 }
Wyatt Rileyc9f25dd2017-05-05 13:45:23 -07001672 // Calculate number of satellites used in fix.
Lifu Tang30f95a72016-01-07 23:20:38 -08001673 int usedInFixCount = 0;
Wyatt Rileyc9f25dd2017-05-05 13:45:23 -07001674 int maxCn0 = 0;
1675 int meanCn0 = 0;
Lifu Tang30f95a72016-01-07 23:20:38 -08001676 for (int i = 0; i < svCount; i++) {
Lifu Tang120480f2016-02-07 18:08:19 -08001677 if ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0) {
Lifu Tang30f95a72016-01-07 23:20:38 -08001678 ++usedInFixCount;
Wyatt Rileyc9f25dd2017-05-05 13:45:23 -07001679 if (mCn0s[i] > maxCn0) {
1680 maxCn0 = (int)mCn0s[i];
1681 }
1682 meanCn0 += mCn0s[i];
Lifu Tang30f95a72016-01-07 23:20:38 -08001683 }
1684 if (VERBOSE) {
Lifu Tang120480f2016-02-07 18:08:19 -08001685 Log.v(TAG, "svid: " + (mSvidWithFlags[i] >> GnssStatus.SVID_SHIFT_WIDTH) +
Wyatt Rileyc9f25dd2017-05-05 13:45:23 -07001686 " cn0: " + mCn0s[i] +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 " elev: " + mSvElevations[i] +
1688 " azimuth: " + mSvAzimuths[i] +
gomo4402af62017-01-11 13:20:13 -08001689 " carrier frequency: " + mSvCarrierFreqs[i] +
Lifu Tang120480f2016-02-07 18:08:19 -08001690 ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) == 0
Lifu Tang30f95a72016-01-07 23:20:38 -08001691 ? " " : " E") +
Lifu Tang120480f2016-02-07 18:08:19 -08001692 ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) == 0
Lifu Tang30f95a72016-01-07 23:20:38 -08001693 ? " " : " A") +
Lifu Tang120480f2016-02-07 18:08:19 -08001694 ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) == 0
gomo4402af62017-01-11 13:20:13 -08001695 ? "" : "U") +
1696 ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_CARRIER_FREQUENCY) == 0
1697 ? "" : "F"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001698 }
1699 }
Wyatt Rileyc9f25dd2017-05-05 13:45:23 -07001700 if (usedInFixCount > 0) {
1701 meanCn0 /= usedInFixCount;
1702 }
1703 // return number of sats used in fix instead of total reported
1704 updateStatus(mStatus, usedInFixCount, meanCn0, maxCn0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001706 if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
Yipeng Cao282b5942017-05-17 20:31:39 -07001707 SystemClock.elapsedRealtime() - mLastFixTime > RECENT_FIX_TIMEOUT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 // send an intent to notify that the GPS is no longer receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001709 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1710 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001711 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Wyatt Rileyc9f25dd2017-05-05 13:45:23 -07001712 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount, mMeanCn0, mMaxCn0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 }
1714 }
Mike Lockwood58bda982009-04-14 16:25:07 -04001715
1716 /**
Mike Lockwoode3635c92009-05-11 08:38:02 -04001717 * called from native code to update AGPS status
Mike Lockwood58bda982009-04-14 16:25:07 -04001718 */
destradaa96a14702014-06-05 11:36:30 -07001719 private void reportAGpsStatus(int type, int status, byte[] ipaddr) {
Mike Lockwood58bda982009-04-14 16:25:07 -04001720 switch (status) {
Mike Lockwoode3635c92009-05-11 08:38:02 -04001721 case GPS_REQUEST_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001722 if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
Andreas Gampee6748ce2015-12-11 18:00:38 -08001723 Log.v(TAG, "Received SUPL IP addr[]: " + Arrays.toString(ipaddr));
destradaae21252a2015-09-08 12:32:59 -07001724 InetAddress connectionIpAddress = null;
destradaa96a14702014-06-05 11:36:30 -07001725 if (ipaddr != null) {
1726 try {
destradaae21252a2015-09-08 12:32:59 -07001727 connectionIpAddress = InetAddress.getByAddress(ipaddr);
1728 if (DEBUG) Log.d(TAG, "IP address converted to: " + connectionIpAddress);
destradaa96a14702014-06-05 11:36:30 -07001729 } catch (UnknownHostException e) {
1730 Log.e(TAG, "Bad IP Address: " + ipaddr, e);
destradaa96a14702014-06-05 11:36:30 -07001731 }
1732 }
destradaae21252a2015-09-08 12:32:59 -07001733 sendMessage(REQUEST_SUPL_CONNECTION, 0 /*arg*/, connectionIpAddress);
Mike Lockwood58bda982009-04-14 16:25:07 -04001734 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001735 case GPS_RELEASE_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001736 if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
destradaae21252a2015-09-08 12:32:59 -07001737 releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
Mike Lockwood58bda982009-04-14 16:25:07 -04001738 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001739 case GPS_AGPS_DATA_CONNECTED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001740 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001741 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001742 case GPS_AGPS_DATA_CONN_DONE:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001743 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
Mike Lockwood58bda982009-04-14 16:25:07 -04001744 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001745 case GPS_AGPS_DATA_CONN_FAILED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001746 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001747 break;
destradaa931a37f2014-08-12 16:36:59 -07001748 default:
Joe Onorato0c484102016-02-01 18:04:24 -08001749 if (DEBUG) Log.d(TAG, "Received Unknown AGPS status: " + status);
Mike Lockwood58bda982009-04-14 16:25:07 -04001750 }
1751 }
1752
destradaae21252a2015-09-08 12:32:59 -07001753 private void releaseSuplConnection(int connStatus) {
1754 sendMessage(RELEASE_SUPL_CONNECTION, connStatus, null /*obj*/);
1755 }
1756
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001757 /**
1758 * called from native code to report NMEA data received
1759 */
Mike Lockwoodf602d362010-06-20 14:28:16 -07001760 private void reportNmea(long timestamp) {
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001761 if (!mItarSpeedLimitExceeded) {
1762 int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
1763 String nmea = new String(mNmeaBuffer, 0 /* offset */, length);
1764 mListenerHelper.onNmeaReceived(timestamp, nmea);
1765 }
destradaaea8a8a62014-06-23 18:19:03 -07001766 }
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001767
destradaaea8a8a62014-06-23 18:19:03 -07001768 /**
Wyatt Rileyaa420d52017-07-03 15:14:42 -07001769 * called from native code - GNSS measurements callback
destradaaea8a8a62014-06-23 18:19:03 -07001770 */
Lifu Tang818aa2c2016-02-01 01:52:00 -08001771 private void reportMeasurementData(GnssMeasurementsEvent event) {
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001772 if (!mItarSpeedLimitExceeded) {
Wyatt Rileyaa420d52017-07-03 15:14:42 -07001773 // send to handler to allow native to return quickly
1774 mHandler.post(new Runnable() {
1775 @Override
1776 public void run() {
1777 mGnssMeasurementsProvider.onMeasurementsAvailable(event);
1778 }
1779 });
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001780 }
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001781 }
1782
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001783 /**
Wyatt Rileyaa420d52017-07-03 15:14:42 -07001784 * called from native code - GNSS navigation message callback
destradaa4b3e3932014-07-21 18:01:47 -07001785 */
Lifu Tange8abe8e2016-04-01 10:32:05 -07001786 private void reportNavigationMessage(GnssNavigationMessage event) {
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001787 if (!mItarSpeedLimitExceeded) {
Wyatt Rileyaa420d52017-07-03 15:14:42 -07001788 // send to handler to allow native to return quickly
1789 mHandler.post(new Runnable() {
1790 @Override
1791 public void run() {
1792 mGnssNavigationMessageProvider.onNavigationMessageAvailable(event);
1793 }
1794 });
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001795 }
destradaa4b3e3932014-07-21 18:01:47 -07001796 }
1797
1798 /**
Mike Lockwood04598b62010-04-14 17:17:24 -04001799 * called from native code to inform us what the GPS engine capabilities are
1800 */
1801 private void setEngineCapabilities(int capabilities) {
1802 mEngineCapabilities = capabilities;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001803
destradaa56b47f82015-07-24 10:56:18 -07001804 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) {
1805 mOnDemandTimeInjection = true;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001806 requestUtcTime();
1807 }
destradaa6568d702014-10-27 12:47:41 -07001808
Lifu Tang818aa2c2016-02-01 01:52:00 -08001809 mGnssMeasurementsProvider.onCapabilitiesUpdated(
destradaa6568d702014-10-27 12:47:41 -07001810 (capabilities & GPS_CAPABILITY_MEASUREMENTS) == GPS_CAPABILITY_MEASUREMENTS);
Lifu Tang818aa2c2016-02-01 01:52:00 -08001811 mGnssNavigationMessageProvider.onCapabilitiesUpdated(
destradaa6568d702014-10-27 12:47:41 -07001812 (capabilities & GPS_CAPABILITY_NAV_MESSAGES) == GPS_CAPABILITY_NAV_MESSAGES);
Mike Lockwood04598b62010-04-14 17:17:24 -04001813 }
1814
1815 /**
Lifu Tang82f893d2016-01-21 18:15:33 -08001816 * Called from native code to inform us the hardware information.
1817 */
Lifu Tang9363b942016-02-16 18:07:00 -08001818 private void setGnssYearOfHardware(int yearOfHardware) {
1819 if (DEBUG) Log.d(TAG, "setGnssYearOfHardware called with " + yearOfHardware);
Lifu Tang82f893d2016-01-21 18:15:33 -08001820 mYearOfHardware = yearOfHardware;
1821 }
1822
Lifu Tang9363b942016-02-16 18:07:00 -08001823 public interface GnssSystemInfoProvider {
Lifu Tang82f893d2016-01-21 18:15:33 -08001824 /**
1825 * Returns the year of GPS hardware.
1826 */
Lifu Tang9363b942016-02-16 18:07:00 -08001827 int getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001828 }
1829
1830 /**
1831 * @hide
1832 */
Lifu Tang9363b942016-02-16 18:07:00 -08001833 public GnssSystemInfoProvider getGnssSystemInfoProvider() {
1834 return new GnssSystemInfoProvider() {
Lifu Tang82f893d2016-01-21 18:15:33 -08001835 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001836 public int getGnssYearOfHardware() {
Lifu Tang82f893d2016-01-21 18:15:33 -08001837 return mYearOfHardware;
1838 }
1839 };
1840 }
1841
Wyatt Rileycf879db2017-01-12 13:57:38 -08001842 public interface GnssBatchingProvider {
1843 /**
1844 * Returns the GNSS batching size
1845 */
1846 int getSize();
1847 /**
1848 * Starts the hardware batching operation
1849 */
1850 boolean start(long periodNanos, boolean wakeOnFifoFull);
1851 /**
1852 * Forces a flush of existing locations from the hardware batching
1853 */
1854 void flush();
1855 /**
1856 * Stops the batching operation
1857 */
1858 boolean stop();
1859 }
1860
1861 /**
1862 * @hide
1863 */
1864 public GnssBatchingProvider getGnssBatchingProvider() {
1865 return new GnssBatchingProvider() {
1866 @Override
1867 public int getSize() {
1868 return native_get_batch_size();
1869 }
1870 @Override
1871 public boolean start(long periodNanos, boolean wakeOnFifoFull) {
1872 if (periodNanos <= 0) {
1873 Log.e(TAG, "Invalid periodNanos " + periodNanos +
1874 "in batching request, not started");
1875 return false;
1876 }
1877 return native_start_batch(periodNanos, wakeOnFifoFull);
1878 }
1879 @Override
1880 public void flush() {
1881 native_flush_batch();
1882 }
1883 @Override
1884 public boolean stop() {
1885 return native_stop_batch();
1886 }
1887 };
1888 }
1889
Siddharth Raybb608c82017-03-16 11:33:34 -07001890 public interface GnssMetricsProvider {
1891 /**
1892 * Returns GNSS metrics as proto string
1893 */
1894 String getGnssMetricsAsProtoString();
1895 }
1896
1897 /**
1898 * @hide
1899 */
1900 public GnssMetricsProvider getGnssMetricsProvider() {
1901 return new GnssMetricsProvider() {
1902 @Override
1903 public String getGnssMetricsAsProtoString() {
1904 return mGnssMetrics.dumpGnssMetricsAsProtoString();
1905 }
1906 };
1907 }
1908
Wyatt Rileycf879db2017-01-12 13:57:38 -08001909 /**
1910 * Initialize Batching if enabled
1911 */
1912 private void enableBatching() {
1913 if (!native_init_batching()) {
1914 Log.e(TAG, "Failed to initialize GNSS batching");
1915 };
1916 }
1917
1918 /**
1919 * Disable batching
1920 */
1921 private void disableBatching() {
1922 native_stop_batch();
1923 native_cleanup_batching();
1924 }
1925
1926 /**
1927 * called from native code - GNSS location batch callback
1928 */
1929 private void reportLocationBatch(Location[] locationArray) {
1930 List<Location> locations = new ArrayList<>(Arrays.asList(locationArray));
1931 if(DEBUG) { Log.d(TAG, "Location batch of size " + locationArray.length + "reported"); }
1932 try {
1933 mILocationManager.reportLocationBatch(locations);
1934 } catch (RemoteException e) {
1935 Log.e(TAG, "RemoteException calling reportLocationBatch");
1936 }
1937 }
1938
Lifu Tang82f893d2016-01-21 18:15:33 -08001939 /**
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001940 * called from native code to request XTRA data
1941 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001942 private void xtraDownloadRequest() {
Joe Onoratof5d95cb2010-01-07 21:48:32 -05001943 if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
Mike Lockwood98e48692010-04-07 16:32:51 -04001944 sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001945 }
1946
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001947 /**
destradaa0682809a2013-08-12 18:50:30 -07001948 * Converts the GPS HAL status to the internal Geofence Hardware status.
1949 */
1950 private int getGeofenceStatus(int status) {
1951 switch(status) {
1952 case GPS_GEOFENCE_OPERATION_SUCCESS:
1953 return GeofenceHardware.GEOFENCE_SUCCESS;
1954 case GPS_GEOFENCE_ERROR_GENERIC:
1955 return GeofenceHardware.GEOFENCE_FAILURE;
1956 case GPS_GEOFENCE_ERROR_ID_EXISTS:
1957 return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS;
1958 case GPS_GEOFENCE_ERROR_INVALID_TRANSITION:
1959 return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION;
1960 case GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES:
1961 return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES;
1962 case GPS_GEOFENCE_ERROR_ID_UNKNOWN:
1963 return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN;
1964 default:
1965 return -1;
1966 }
1967 }
1968
1969 /**
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001970 * Called from native to report GPS Geofence transition
1971 * All geofence callbacks are called on the same thread
1972 */
Wyatt Riley5d229832017-02-10 17:06:00 -08001973 private void reportGeofenceTransition(int geofenceId, Location location, int transition,
1974 long transitionTimestamp) {
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001975 if (mGeofenceHardwareImpl == null) {
1976 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1977 }
Wyatt Riley5d229832017-02-10 17:06:00 -08001978
destradaa0682809a2013-08-12 18:50:30 -07001979 mGeofenceHardwareImpl.reportGeofenceTransition(
1980 geofenceId,
1981 location,
1982 transition,
1983 transitionTimestamp,
1984 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1985 FusedBatchOptions.SourceTechnologies.GNSS);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001986 }
1987
1988 /**
1989 * called from native code to report GPS status change.
1990 */
Wyatt Riley5d229832017-02-10 17:06:00 -08001991 private void reportGeofenceStatus(int status, Location location) {
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001992 if (mGeofenceHardwareImpl == null) {
1993 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1994 }
destradaa0682809a2013-08-12 18:50:30 -07001995 int monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
1996 if(status == GPS_GEOFENCE_AVAILABLE) {
1997 monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE;
1998 }
1999 mGeofenceHardwareImpl.reportGeofenceMonitorStatus(
2000 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
2001 monitorStatus,
2002 location,
2003 FusedBatchOptions.SourceTechnologies.GNSS);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07002004 }
2005
2006 /**
2007 * called from native code - Geofence Add callback
2008 */
2009 private void reportGeofenceAddStatus(int geofenceId, int status) {
2010 if (mGeofenceHardwareImpl == null) {
2011 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
2012 }
destradaa0682809a2013-08-12 18:50:30 -07002013 mGeofenceHardwareImpl.reportGeofenceAddStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07002014 }
2015
2016 /**
2017 * called from native code - Geofence Remove callback
2018 */
2019 private void reportGeofenceRemoveStatus(int geofenceId, int status) {
2020 if (mGeofenceHardwareImpl == null) {
2021 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
2022 }
destradaa0682809a2013-08-12 18:50:30 -07002023 mGeofenceHardwareImpl.reportGeofenceRemoveStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07002024 }
2025
2026 /**
2027 * called from native code - Geofence Pause callback
2028 */
2029 private void reportGeofencePauseStatus(int geofenceId, int status) {
2030 if (mGeofenceHardwareImpl == null) {
2031 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
2032 }
destradaa0682809a2013-08-12 18:50:30 -07002033 mGeofenceHardwareImpl.reportGeofencePauseStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07002034 }
2035
2036 /**
2037 * called from native code - Geofence Resume callback
2038 */
2039 private void reportGeofenceResumeStatus(int geofenceId, int status) {
2040 if (mGeofenceHardwareImpl == null) {
2041 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
2042 }
destradaa0682809a2013-08-12 18:50:30 -07002043 mGeofenceHardwareImpl.reportGeofenceResumeStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07002044 }
2045
Danke Xie22d1f9f2009-08-18 18:28:45 -04002046 //=============================================================
2047 // NI Client support
Miguel Torroja1e84da82010-07-27 07:02:24 +02002048 //=============================================================
Danke Xie22d1f9f2009-08-18 18:28:45 -04002049 private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
destradaaef752b62015-04-17 13:10:47 -07002050 // Sends a response for an NI request to HAL.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002051 @Override
Miguel Torroja1e84da82010-07-27 07:02:24 +02002052 public boolean sendNiResponse(int notificationId, int userResponse)
2053 {
2054 // TODO Add Permission check
Danke Xie22d1f9f2009-08-18 18:28:45 -04002055
Miguel Torroja1e84da82010-07-27 07:02:24 +02002056 if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
2057 ", response: " + userResponse);
2058 native_send_ni_response(notificationId, userResponse);
2059 return true;
2060 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002061 };
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002062
Danke Xie22d1f9f2009-08-18 18:28:45 -04002063 public INetInitiatedListener getNetInitiatedListener() {
2064 return mNetInitiatedListener;
2065 }
2066
2067 // Called by JNI function to report an NI request.
Miguel Torroja1e84da82010-07-27 07:02:24 +02002068 public void reportNiNotification(
2069 int notificationId,
2070 int niType,
2071 int notifyFlags,
2072 int timeout,
2073 int defaultResponse,
2074 String requestorId,
2075 String text,
2076 int requestorIdEncoding,
Hridya Valsaraju2ea29602016-09-13 08:38:09 -07002077 int textEncoding
Danke Xie22d1f9f2009-08-18 18:28:45 -04002078 )
Miguel Torroja1e84da82010-07-27 07:02:24 +02002079 {
2080 Log.i(TAG, "reportNiNotification: entered");
2081 Log.i(TAG, "notificationId: " + notificationId +
2082 ", niType: " + niType +
2083 ", notifyFlags: " + notifyFlags +
2084 ", timeout: " + timeout +
2085 ", defaultResponse: " + defaultResponse);
2086
2087 Log.i(TAG, "requestorId: " + requestorId +
2088 ", text: " + text +
2089 ", requestorIdEncoding: " + requestorIdEncoding +
2090 ", textEncoding: " + textEncoding);
2091
2092 GpsNiNotification notification = new GpsNiNotification();
2093
2094 notification.notificationId = notificationId;
2095 notification.niType = niType;
2096 notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
2097 notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
2098 notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
2099 notification.timeout = timeout;
2100 notification.defaultResponse = defaultResponse;
2101 notification.requestorId = requestorId;
2102 notification.text = text;
2103 notification.requestorIdEncoding = requestorIdEncoding;
2104 notification.textEncoding = textEncoding;
2105
Miguel Torroja1e84da82010-07-27 07:02:24 +02002106 mNIHandler.handleNiNotification(notification);
2107 }
2108
2109 /**
2110 * Called from native code to request set id info.
2111 * We should be careful about receiving null string from the TelephonyManager,
2112 * because sending null String to JNI function would cause a crash.
2113 */
2114
2115 private void requestSetID(int flags) {
2116 TelephonyManager phone = (TelephonyManager)
2117 mContext.getSystemService(Context.TELEPHONY_SERVICE);
destradaaef752b62015-04-17 13:10:47 -07002118 int type = AGPS_SETID_TYPE_NONE;
Miguel Torroja1e84da82010-07-27 07:02:24 +02002119 String data = "";
2120
2121 if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
2122 String data_temp = phone.getSubscriberId();
2123 if (data_temp == null) {
2124 // This means the framework does not have the SIM card ready.
2125 } else {
2126 // This means the framework has the SIM card.
2127 data = data_temp;
2128 type = AGPS_SETID_TYPE_IMSI;
2129 }
2130 }
2131 else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
2132 String data_temp = phone.getLine1Number();
2133 if (data_temp == null) {
2134 // This means the framework does not have the SIM card ready.
2135 } else {
2136 // This means the framework has the SIM card.
2137 data = data_temp;
2138 type = AGPS_SETID_TYPE_MSISDN;
2139 }
2140 }
2141 native_agps_set_id(type, data);
2142 }
2143
2144 /**
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04002145 * Called from native code to request utc time info
2146 */
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04002147 private void requestUtcTime() {
destradaae21252a2015-09-08 12:32:59 -07002148 if (DEBUG) Log.d(TAG, "utcTimeRequest");
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04002149 sendMessage(INJECT_NTP_TIME, 0, null);
2150 }
2151
2152 /**
Miguel Torroja1e84da82010-07-27 07:02:24 +02002153 * Called from native code to request reference location info
2154 */
2155
Hridya Valsaraju2ea29602016-09-13 08:38:09 -07002156 private void requestRefLocation() {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002157 TelephonyManager phone = (TelephonyManager)
2158 mContext.getSystemService(Context.TELEPHONY_SERVICE);
Victoria Leased50d0c32012-10-29 13:16:17 -07002159 final int phoneType = phone.getPhoneType();
2160 if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002161 GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation();
Victoria Leased50d0c32012-10-29 13:16:17 -07002162 if ((gsm_cell != null) && (phone.getNetworkOperator() != null)
2163 && (phone.getNetworkOperator().length() > 3)) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002164 int type;
2165 int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0,3));
2166 int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3));
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002167 int networkType = phone.getNetworkType();
2168 if (networkType == TelephonyManager.NETWORK_TYPE_UMTS
2169 || networkType == TelephonyManager.NETWORK_TYPE_HSDPA
2170 || networkType == TelephonyManager.NETWORK_TYPE_HSUPA
Arun Ravindran58d46122012-07-30 17:50:21 +03002171 || networkType == TelephonyManager.NETWORK_TYPE_HSPA
2172 || networkType == TelephonyManager.NETWORK_TYPE_HSPAP) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002173 type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002174 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002175 type = AGPS_REF_LOCATION_TYPE_GSM_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002176 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02002177 native_agps_set_ref_location_cellid(type, mcc, mnc,
2178 gsm_cell.getLac(), gsm_cell.getCid());
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002179 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002180 Log.e(TAG,"Error getting cell location info.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002181 }
Victoria Leased50d0c32012-10-29 13:16:17 -07002182 } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
2183 Log.e(TAG, "CDMA not supported.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002184 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02002185 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002186
Mike Lockwood98e48692010-04-07 16:32:51 -04002187 private void sendMessage(int message, int arg, Object obj) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002188 // hold a wake lock until this message is delivered
Jeff Brown028872f2012-08-25 13:07:01 -07002189 // note that this assumes the message will not be removed from the queue before
2190 // it is handled (otherwise the wake lock would be leaked).
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002191 mWakeLock.acquire();
Wyatt Rileycf879db2017-01-12 13:57:38 -08002192 if (Log.isLoggable(TAG, Log.INFO)) {
2193 Log.i(TAG, "WakeLock acquired by sendMessage(" + messageIdAsString(message) + ", " + arg
2194 + ", " + obj + ")");
2195 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002196 mHandler.obtainMessage(message, arg, 1, obj).sendToTarget();
Mike Lockwood98e48692010-04-07 16:32:51 -04002197 }
2198
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002199 private final class ProviderHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08002200 public ProviderHandler(Looper looper) {
2201 super(looper, null, true /*async*/);
Jeff Brown028872f2012-08-25 13:07:01 -07002202 }
2203
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002204 @Override
Mike Lockwood4a7b65e2010-10-25 16:35:55 -04002205 public void handleMessage(Message msg) {
Mike Lockwood98e48692010-04-07 16:32:51 -04002206 int message = msg.what;
2207 switch (message) {
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002208 case ENABLE:
2209 if (msg.arg1 == 1) {
2210 handleEnable();
2211 } else {
2212 handleDisable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002213 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002214 break;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002215 case SET_REQUEST:
2216 GpsRequest gpsRequest = (GpsRequest) msg.obj;
2217 handleSetRequest(gpsRequest.request, gpsRequest.source);
Mike Lockwood03ca2162010-04-01 08:10:09 -07002218 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002219 case UPDATE_NETWORK_STATE:
destradaae21252a2015-09-08 12:32:59 -07002220 handleUpdateNetworkState((Network) msg.obj);
2221 break;
2222 case REQUEST_SUPL_CONNECTION:
2223 handleRequestSuplConnection((InetAddress) msg.obj);
2224 break;
2225 case RELEASE_SUPL_CONNECTION:
2226 handleReleaseSuplConnection(msg.arg1);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002227 break;
2228 case INJECT_NTP_TIME:
2229 handleInjectNtpTime();
2230 break;
2231 case DOWNLOAD_XTRA_DATA:
Wyatt Riley0d6e54e22016-10-05 12:03:03 -07002232 handleDownloadXtraData();
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002233 break;
Kevin Tang40e1baf2012-01-10 14:32:44 -08002234 case INJECT_NTP_TIME_FINISHED:
2235 mInjectNtpTimePending = STATE_IDLE;
2236 break;
2237 case DOWNLOAD_XTRA_DATA_FINISHED:
2238 mDownloadXtraDataPending = STATE_IDLE;
2239 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002240 case UPDATE_LOCATION:
destradaae21252a2015-09-08 12:32:59 -07002241 handleUpdateLocation((Location) msg.obj);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002242 break;
destradaafb23c672015-04-16 14:01:27 -07002243 case SUBSCRIPTION_OR_SIM_CHANGED:
2244 subscriptionOrSimChanged(mContext);
2245 break;
2246 case INITIALIZE_HANDLER:
destradaae21252a2015-09-08 12:32:59 -07002247 handleInitialize();
destradaafb23c672015-04-16 14:01:27 -07002248 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002249 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002250 if (msg.arg2 == 1) {
2251 // wakelock was taken for this message, release it
2252 mWakeLock.release();
Wyatt Rileycf879db2017-01-12 13:57:38 -08002253 if (Log.isLoggable(TAG, Log.INFO)) {
2254 Log.i(TAG, "WakeLock released by handleMessage(" + messageIdAsString(message)
2255 + ", " + msg.arg1 + ", " + msg.obj + ")");
2256 }
Mike Lockwood98e48692010-04-07 16:32:51 -04002257 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002258 }
destradaafb23c672015-04-16 14:01:27 -07002259
2260 /**
Lifu Tang30f95a72016-01-07 23:20:38 -08002261 * This method is bound to {@link #GnssLocationProvider(Context, ILocationManager, Looper)}.
destradaafb23c672015-04-16 14:01:27 -07002262 * It is in charge of loading properties and registering for events that will be posted to
2263 * this handler.
2264 */
destradaae21252a2015-09-08 12:32:59 -07002265 private void handleInitialize() {
destradaafb23c672015-04-16 14:01:27 -07002266 // load default GPS configuration
2267 // (this configuration might change in the future based on SIM changes)
2268 reloadGpsProperties(mContext, mProperties);
2269
2270 // TODO: When this object "finishes" we should unregister by invoking
2271 // SubscriptionManager.getInstance(mContext).unregister(mOnSubscriptionsChangedListener);
2272 // This is not strictly necessary because it will be unregistered if the
2273 // notification fails but it is good form.
2274
2275 // Register for SubscriptionInfo list changes which is guaranteed
2276 // to invoke onSubscriptionsChanged the first time.
2277 SubscriptionManager.from(mContext)
2278 .addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
2279
2280 // listen for events
destradaaef752b62015-04-17 13:10:47 -07002281 IntentFilter intentFilter;
2282 if (native_is_agps_ril_supported()) {
2283 intentFilter = new IntentFilter();
2284 intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
2285 intentFilter.addDataScheme("sms");
2286 intentFilter.addDataAuthority("localhost", "7275");
2287 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
destradaafb23c672015-04-16 14:01:27 -07002288
destradaaef752b62015-04-17 13:10:47 -07002289 intentFilter = new IntentFilter();
2290 intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
2291 try {
2292 intentFilter.addDataType("application/vnd.omaloc-supl-init");
2293 } catch (IntentFilter.MalformedMimeTypeException e) {
2294 Log.w(TAG, "Malformed SUPL init mime type");
2295 }
2296 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
2297 } else if (DEBUG) {
2298 Log.d(TAG, "Skipped registration for SMS/WAP-PUSH messages because AGPS Ril in GPS"
2299 + " HAL is not supported");
destradaafb23c672015-04-16 14:01:27 -07002300 }
destradaafb23c672015-04-16 14:01:27 -07002301
2302 intentFilter = new IntentFilter();
2303 intentFilter.addAction(ALARM_WAKEUP);
2304 intentFilter.addAction(ALARM_TIMEOUT);
destradaafb23c672015-04-16 14:01:27 -07002305 intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
Adam Lesinski87c17df2015-05-27 13:24:13 -07002306 intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
destradaafb23c672015-04-16 14:01:27 -07002307 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
2308 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
2309 intentFilter.addAction(SIM_STATE_CHANGED);
2310 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
2311
destradaae21252a2015-09-08 12:32:59 -07002312 // register for connectivity change events, this is equivalent to the deprecated way of
2313 // registering for CONNECTIVITY_ACTION broadcasts
2314 NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder();
2315 networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
2316 networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
Zheng Zhangd6886712017-08-22 10:27:14 -07002317 networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_BLUETOOTH);
destradaae21252a2015-09-08 12:32:59 -07002318 NetworkRequest networkRequest = networkRequestBuilder.build();
2319 mConnMgr.registerNetworkCallback(networkRequest, mNetworkConnectivityCallback);
2320
destradaafb23c672015-04-16 14:01:27 -07002321 // listen for PASSIVE_PROVIDER updates
2322 LocationManager locManager =
2323 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
2324 long minTime = 0;
2325 float minDistance = 0;
2326 boolean oneShot = false;
2327 LocationRequest request = LocationRequest.createFromDeprecatedProvider(
2328 LocationManager.PASSIVE_PROVIDER,
2329 minTime,
2330 minDistance,
2331 oneShot);
2332 // Don't keep track of this request since it's done on behalf of other clients
2333 // (which are kept track of separately).
2334 request.setHideFromAppOps(true);
2335 locManager.requestLocationUpdates(
2336 request,
2337 new NetworkLocationListener(),
2338 getLooper());
2339 }
2340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002341
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002342 private final class NetworkLocationListener implements LocationListener {
2343 @Override
2344 public void onLocationChanged(Location location) {
2345 // this callback happens on mHandler looper
2346 if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
2347 handleUpdateLocation(location);
2348 }
2349 }
2350 @Override
2351 public void onStatusChanged(String provider, int status, Bundle extras) { }
2352 @Override
2353 public void onProviderEnabled(String provider) { }
2354 @Override
2355 public void onProviderDisabled(String provider) { }
2356 }
2357
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002358 private String getSelectedApn() {
2359 Uri uri = Uri.parse("content://telephony/carriers/preferapn");
destradaa96a14702014-06-05 11:36:30 -07002360 Cursor cursor = null;
2361 try {
2362 cursor = mContext.getContentResolver().query(
2363 uri,
2364 new String[] { "apn" },
2365 null /* selection */,
2366 null /* selectionArgs */,
2367 Carriers.DEFAULT_SORT_ORDER);
2368 if (cursor != null && cursor.moveToFirst()) {
2369 return cursor.getString(0);
2370 } else {
2371 Log.e(TAG, "No APN found to select.");
2372 }
2373 } catch (Exception e) {
destradaaea8a8a62014-06-23 18:19:03 -07002374 Log.e(TAG, "Error encountered on selecting the APN.", e);
destradaa96a14702014-06-05 11:36:30 -07002375 } finally {
2376 if (cursor != null) {
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002377 cursor.close();
2378 }
2379 }
destradaa96a14702014-06-05 11:36:30 -07002380
2381 return null;
2382 }
2383
2384 private int getApnIpType(String apn) {
destradaae21252a2015-09-08 12:32:59 -07002385 ensureInHandlerThread();
destradaa96a14702014-06-05 11:36:30 -07002386 if (apn == null) {
2387 return APN_INVALID;
2388 }
2389
destradaa96a14702014-06-05 11:36:30 -07002390 String selection = String.format("current = 1 and apn = '%s' and carrier_enabled = 1", apn);
2391 Cursor cursor = null;
2392 try {
2393 cursor = mContext.getContentResolver().query(
2394 Carriers.CONTENT_URI,
2395 new String[] { Carriers.PROTOCOL },
2396 selection,
2397 null,
2398 Carriers.DEFAULT_SORT_ORDER);
2399
2400 if (null != cursor && cursor.moveToFirst()) {
2401 return translateToApnIpType(cursor.getString(0), apn);
2402 } else {
2403 Log.e(TAG, "No entry found in query for APN: " + apn);
2404 }
2405 } catch (Exception e) {
2406 Log.e(TAG, "Error encountered on APN query for: " + apn, e);
2407 } finally {
2408 if (cursor != null) {
2409 cursor.close();
2410 }
2411 }
2412
2413 return APN_INVALID;
2414 }
2415
2416 private int translateToApnIpType(String ipProtocol, String apn) {
2417 if ("IP".equals(ipProtocol)) {
2418 return APN_IPV4;
2419 }
2420 if ("IPV6".equals(ipProtocol)) {
2421 return APN_IPV6;
2422 }
2423 if ("IPV4V6".equals(ipProtocol)) {
2424 return APN_IPV4V6;
2425 }
2426
2427 // we hit the default case so the ipProtocol is not recognized
2428 String message = String.format("Unknown IP Protocol: %s, for APN: %s", ipProtocol, apn);
2429 Log.e(TAG, message);
2430 return APN_INVALID;
2431 }
2432
2433 private void setRouting() {
2434 if (mAGpsDataConnectionIpAddr == null) {
2435 return;
2436 }
2437
destradaae21252a2015-09-08 12:32:59 -07002438 // TODO: replace the use of this deprecated API
destradaa96a14702014-06-05 11:36:30 -07002439 boolean result = mConnMgr.requestRouteToHostAddress(
2440 ConnectivityManager.TYPE_MOBILE_SUPL,
2441 mAGpsDataConnectionIpAddr);
2442
2443 if (!result) {
2444 Log.e(TAG, "Error requesting route to host: " + mAGpsDataConnectionIpAddr);
2445 } else if (DEBUG) {
2446 Log.d(TAG, "Successfully requested route to host: " + mAGpsDataConnectionIpAddr);
2447 }
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002448 }
2449
destradaae21252a2015-09-08 12:32:59 -07002450 /**
2451 * @return {@code true} if there is a data network available for outgoing connections,
2452 * {@code false} otherwise.
2453 */
2454 private boolean isDataNetworkConnected() {
2455 NetworkInfo activeNetworkInfo = mConnMgr.getActiveNetworkInfo();
2456 return activeNetworkInfo != null && activeNetworkInfo.isConnected();
2457 }
2458
2459 /**
2460 * Ensures the calling function is running in the thread associated with {@link #mHandler}.
2461 */
2462 private void ensureInHandlerThread() {
2463 if (mHandler != null && Looper.myLooper() == mHandler.getLooper()) {
2464 return;
2465 }
2466 throw new RuntimeException("This method must run on the Handler thread.");
2467 }
2468
2469 /**
2470 * @return A string representing the current state stored in {@link #mAGpsDataConnectionState}.
2471 */
2472 private String agpsDataConnStateAsString() {
2473 switch(mAGpsDataConnectionState) {
2474 case AGPS_DATA_CONNECTION_CLOSED:
2475 return "CLOSED";
2476 case AGPS_DATA_CONNECTION_OPEN:
2477 return "OPEN";
2478 case AGPS_DATA_CONNECTION_OPENING:
2479 return "OPENING";
2480 default:
2481 return "<Unknown>";
2482 }
2483 }
2484
2485 /**
2486 * @return A string representing the given GPS_AGPS_DATA status.
2487 */
2488 private String agpsDataConnStatusAsString(int agpsDataConnStatus) {
2489 switch (agpsDataConnStatus) {
2490 case GPS_AGPS_DATA_CONNECTED:
2491 return "CONNECTED";
2492 case GPS_AGPS_DATA_CONN_DONE:
2493 return "DONE";
2494 case GPS_AGPS_DATA_CONN_FAILED:
2495 return "FAILED";
2496 case GPS_RELEASE_AGPS_DATA_CONN:
2497 return "RELEASE";
2498 case GPS_REQUEST_AGPS_DATA_CONN:
2499 return "REQUEST";
2500 default:
2501 return "<Unknown>";
2502 }
2503 }
2504
Wyatt Rileycf879db2017-01-12 13:57:38 -08002505 /**
2506 * @return A string representing the given message ID.
2507 */
2508 private String messageIdAsString(int message) {
2509 switch (message) {
2510 case ENABLE:
2511 return "ENABLE";
2512 case SET_REQUEST:
2513 return "SET_REQUEST";
2514 case UPDATE_NETWORK_STATE:
2515 return "UPDATE_NETWORK_STATE";
2516 case REQUEST_SUPL_CONNECTION:
2517 return "REQUEST_SUPL_CONNECTION";
2518 case RELEASE_SUPL_CONNECTION:
2519 return "RELEASE_SUPL_CONNECTION";
2520 case INJECT_NTP_TIME:
2521 return "INJECT_NTP_TIME";
2522 case DOWNLOAD_XTRA_DATA:
2523 return "DOWNLOAD_XTRA_DATA";
2524 case INJECT_NTP_TIME_FINISHED:
2525 return "INJECT_NTP_TIME_FINISHED";
2526 case DOWNLOAD_XTRA_DATA_FINISHED:
2527 return "DOWNLOAD_XTRA_DATA_FINISHED";
2528 case UPDATE_LOCATION:
2529 return "UPDATE_LOCATION";
2530 case SUBSCRIPTION_OR_SIM_CHANGED:
2531 return "SUBSCRIPTION_OR_SIM_CHANGED";
2532 case INITIALIZE_HANDLER:
2533 return "INITIALIZE_HANDLER";
2534 default:
2535 return "<Unknown>";
2536 }
2537 }
2538
Siddharth Raybb608c82017-03-16 11:33:34 -07002539
2540
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002541 @Override
2542 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2543 StringBuilder s = new StringBuilder();
Wyatt Riley77ca4f82017-06-30 18:13:44 -07002544 s.append(" mStarted=").append(mStarted).append('\n');
destradaa25e8caf2015-08-24 14:14:44 -07002545 s.append(" mFixInterval=").append(mFixInterval).append('\n');
2546 s.append(" mDisableGps (battery saver mode)=").append(mDisableGps).append('\n');
2547 s.append(" mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities));
2548 s.append(" ( ");
2549 if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHEDULING ");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002550 if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
2551 if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA ");
2552 if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT ");
2553 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME ");
destradaa25e8caf2015-08-24 14:14:44 -07002554 if (hasCapability(GPS_CAPABILITY_GEOFENCING)) s.append("GEOFENCING ");
2555 if (hasCapability(GPS_CAPABILITY_MEASUREMENTS)) s.append("MEASUREMENTS ");
2556 if (hasCapability(GPS_CAPABILITY_NAV_MESSAGES)) s.append("NAV_MESSAGES ");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002557 s.append(")\n");
Siddharth Raybb608c82017-03-16 11:33:34 -07002558 s.append(mGnssMetrics.dumpGnssMetricsAsText());
2559 s.append(" native internal state: ").append(native_get_internal_state());
Wyatt Rileycf879db2017-01-12 13:57:38 -08002560 s.append("\n");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002561 pw.append(s);
2562 }
2563
Wei Liu6f6326b2015-06-24 23:47:50 -07002564 /**
2565 * A simple implementation of exponential backoff.
2566 */
2567 private static final class BackOff {
2568 private static final int MULTIPLIER = 2;
2569 private final long mInitIntervalMillis;
2570 private final long mMaxIntervalMillis;
2571 private long mCurrentIntervalMillis;
2572
2573 public BackOff(long initIntervalMillis, long maxIntervalMillis) {
2574 mInitIntervalMillis = initIntervalMillis;
2575 mMaxIntervalMillis = maxIntervalMillis;
2576
2577 mCurrentIntervalMillis = mInitIntervalMillis / MULTIPLIER;
2578 }
2579
2580 public long nextBackoffMillis() {
2581 if (mCurrentIntervalMillis > mMaxIntervalMillis) {
2582 return mMaxIntervalMillis;
2583 }
2584
2585 mCurrentIntervalMillis *= MULTIPLIER;
2586 return mCurrentIntervalMillis;
2587 }
2588
2589 public void reset() {
2590 mCurrentIntervalMillis = mInitIntervalMillis / MULTIPLIER;
2591 }
2592 }
2593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002594 // for GPS SV statistics
Lifu Tang120480f2016-02-07 18:08:19 -08002595 private static final int MAX_SVS = 64;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002596
2597 // preallocated arrays, to avoid memory allocation in reportStatus()
Lifu Tang120480f2016-02-07 18:08:19 -08002598 private int mSvidWithFlags[] = new int[MAX_SVS];
Lifu Tang76a620f2016-02-26 19:53:01 -08002599 private float mCn0s[] = new float[MAX_SVS];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002600 private float mSvElevations[] = new float[MAX_SVS];
2601 private float mSvAzimuths[] = new float[MAX_SVS];
gomo4402af62017-01-11 13:20:13 -08002602 private float mSvCarrierFreqs[] = new float[MAX_SVS];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002603 private int mSvCount;
Wyatt Rileyc9f25dd2017-05-05 13:45:23 -07002604 private int mMeanCn0;
2605 private int mMaxCn0;
Mike Lockwoodb16e7802009-08-06 09:26:02 -04002606 // preallocated to avoid memory allocation in reportNmea()
2607 private byte[] mNmeaBuffer = new byte[120];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002608
gomo4402af62017-01-11 13:20:13 -08002609 static { class_init_native(); }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002610 private static native void class_init_native();
2611 private static native boolean native_is_supported();
destradaaef752b62015-04-17 13:10:47 -07002612 private static native boolean native_is_agps_ril_supported();
2613 private static native boolean native_is_gnss_configuration_supported();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002614
2615 private native boolean native_init();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002616 private native void native_cleanup();
Mike Lockwood04598b62010-04-14 17:17:24 -04002617 private native boolean native_set_position_mode(int mode, int recurrence, int min_interval,
2618 int preferred_accuracy, int preferred_time);
2619 private native boolean native_start();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002620 private native boolean native_stop();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002621 private native void native_delete_aiding_data(int flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 // returns number of SVs
2623 // mask[0] is ephemeris mask and mask[1] is almanac mask
Lifu Tang76a620f2016-02-26 19:53:01 -08002624 private native int native_read_sv_status(int[] prnWithFlags, float[] cn0s, float[] elevations,
gomo4402af62017-01-11 13:20:13 -08002625 float[] azimuths, float[] carrierFrequencies);
Mike Lockwoodf602d362010-06-20 14:28:16 -07002626 private native int native_read_nmea(byte[] buffer, int bufferSize);
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -04002627 private native void native_inject_location(double latitude, double longitude, float accuracy);
2628
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06002629 // XTRA Support
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002630 private native void native_inject_time(long time, long timeReference, int uncertainty);
2631 private native boolean native_supports_xtra();
2632 private native void native_inject_xtra_data(byte[] data, int length);
The Android Open Source Project10592532009-03-18 17:39:46 -07002633
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06002634 // DEBUG Support
2635 private native String native_get_internal_state();
2636
2637 // AGPS Support
destradaa96a14702014-06-05 11:36:30 -07002638 private native void native_agps_data_conn_open(String apn, int apnIpType);
Mike Lockwoode3635c92009-05-11 08:38:02 -04002639 private native void native_agps_data_conn_closed();
2640 private native void native_agps_data_conn_failed();
Miguel Torroja1e84da82010-07-27 07:02:24 +02002641 private native void native_agps_ni_message(byte [] msg, int length);
Mike Lockwooda9e54612009-06-19 14:54:42 -04002642 private native void native_set_agps_server(int type, String hostname, int port);
Danke Xie22d1f9f2009-08-18 18:28:45 -04002643
2644 // Network-initiated (NI) Support
2645 private native void native_send_ni_response(int notificationId, int userResponse);
Miguel Torroja1e84da82010-07-27 07:02:24 +02002646
2647 // AGPS ril suport
2648 private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
2649 int lac, int cid);
2650 private native void native_agps_set_id(int type, String setid);
Mike Lockwood50130bb2010-10-11 06:22:50 -04002651
2652 private native void native_update_network_state(boolean connected, int type,
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002653 boolean roaming, boolean available, String extraInfo, String defaultAPN);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07002654
2655 // Hardware Geofence support.
2656 private static native boolean native_is_geofence_supported();
2657 private static native boolean native_add_geofence(int geofenceId, double latitude,
2658 double longitude, double radius, int lastTransition,int monitorTransitions,
2659 int notificationResponsivenes, int unknownTimer);
2660 private static native boolean native_remove_geofence(int geofenceId);
2661 private static native boolean native_resume_geofence(int geofenceId, int transitions);
2662 private static native boolean native_pause_geofence(int geofenceId);
destradaaea8a8a62014-06-23 18:19:03 -07002663
2664 // Gps Hal measurements support.
2665 private static native boolean native_is_measurement_supported();
destradaa4b3e3932014-07-21 18:01:47 -07002666 private native boolean native_start_measurement_collection();
2667 private native boolean native_stop_measurement_collection();
2668
2669 // Gps Navigation message support.
2670 private static native boolean native_is_navigation_message_supported();
2671 private native boolean native_start_navigation_message_collection();
2672 private native boolean native_stop_navigation_message_collection();
Tsuwei Chen52617bb2014-08-25 11:49:11 -07002673
2674 // GNSS Configuration
Hridya Valsaraju2ea29602016-09-13 08:38:09 -07002675 private static native boolean native_set_supl_version(int version);
2676 private static native boolean native_set_supl_mode(int mode);
2677 private static native boolean native_set_supl_es(int es);
2678 private static native boolean native_set_lpp_profile(int lppProfile);
2679 private static native boolean native_set_gnss_pos_protocol_select(int gnssPosProtocolSelect);
2680 private static native boolean native_set_gps_lock(int gpsLock);
2681 private static native boolean native_set_emergency_supl_pdn(int emergencySuplPdn);
2682
Wyatt Rileycf879db2017-01-12 13:57:38 -08002683 // GNSS Batching
2684 private static native int native_get_batch_size();
2685 private static native boolean native_start_batch(long periodNanos, boolean wakeOnFifoFull);
2686 private static native void native_flush_batch();
2687 private static native boolean native_stop_batch();
2688 private static native boolean native_init_batching();
2689 private static native void native_cleanup_batching();
2690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002691}