blob: 9e6e3812df6b5a0fba4bea71ec0e4fe001b12b79 [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;
Yu-Han Yang74041ff2018-04-06 15:57:31 -070023import android.content.ContentResolver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.Context;
25import android.content.Intent;
The Android Open Source Project10592532009-03-18 17:39:46 -070026import android.content.IntentFilter;
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;
Yu-Han Yange7baef32018-02-09 13:58:17 -080031import android.location.GnssMeasurementsEvent;
32import android.location.GnssNavigationMessage;
Lifu Tang30f95a72016-01-07 23:20:38 -080033import android.location.GnssStatus;
34import android.location.IGnssStatusListener;
35import android.location.IGnssStatusProvider;
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;
Kevin Tang40e1baf2012-01-10 14:32:44 -080044import android.os.AsyncTask;
Dianne Hackborn91268cf2013-06-13 19:06:50 -070045import android.os.BatteryStats;
Mike Lockwood63aa5a62010-04-14 19:21:31 -040046import android.os.Binder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.os.Bundle;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040048import android.os.Handler;
Victoria Lease5cd731a2012-12-19 15:04:21 -080049import android.os.Looper;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040050import android.os.Message;
Yu-Han Yange7baef32018-02-09 13:58:17 -080051import android.os.PersistableBundle;
Mike Lockwood0528b9b2009-05-07 10:12:54 -040052import android.os.PowerManager;
Yu-Han Yange7baef32018-02-09 13:58:17 -080053import android.os.PowerManager.ServiceType;
54import android.os.PowerSaveState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.os.RemoteException;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -040056import android.os.ServiceManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import android.os.SystemClock;
Colin Cross7c030ed2014-01-28 09:33:53 -080058import android.os.SystemProperties;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070059import android.os.UserHandle;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070060import android.os.WorkSource;
Narayan Kamath32684dd2018-01-08 17:32:51 +000061import android.os.WorkSource.WorkChain;
Mike Lockwoodbcab8df2009-06-25 16:39:09 -040062import android.provider.Settings;
Yu-Han Yange7baef32018-02-09 13:58:17 -080063import android.telephony.CarrierConfigManager;
Wink Savillea374c3d2014-11-11 11:48:04 -080064import android.telephony.SubscriptionManager;
Wink Savilled09c4ca2014-11-22 10:08:16 -080065import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
Miguel Torroja1e84da82010-07-27 07:02:24 +020066import android.telephony.TelephonyManager;
67import android.telephony.gsm.GsmCellLocation;
Colin Cross7c030ed2014-01-28 09:33:53 -080068import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069import android.util.Log;
Yu-Han Yanga1862b52018-02-20 17:05:59 -080070
jackqdyulei455e90a2017-02-09 15:29:16 -080071import com.android.internal.app.IBatteryStats;
72import com.android.internal.location.GpsNetInitiatedHandler;
73import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
74import com.android.internal.location.ProviderProperties;
75import com.android.internal.location.ProviderRequest;
Yu-Han Yange7baef32018-02-09 13:58:17 -080076import com.android.internal.location.gnssmetrics.GnssMetrics;
Yu-Han Yang66c7ea92018-03-11 17:17:15 -070077import com.android.server.location.GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback;
Yu-Han Yanga1862b52018-02-20 17:05:59 -080078import com.android.server.location.NtpTimeHelper.InjectNtpTimeCallback;
Yu-Han Yang66c7ea92018-03-11 17:17:15 -070079
80import libcore.io.IoUtils;
81
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import java.io.File;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070083import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import java.io.FileInputStream;
85import java.io.IOException;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070086import java.io.PrintWriter;
Wyatt Rileycf879db2017-01-12 13:57:38 -080087import java.util.ArrayList;
Andreas Gampee6748ce2015-12-11 18:00:38 -080088import java.util.Arrays;
Yu-Han Yange7baef32018-02-09 13:58:17 -080089import java.util.HashMap;
Wyatt Rileycf879db2017-01-12 13:57:38 -080090import java.util.List;
Yu-Han Yange7baef32018-02-09 13:58:17 -080091import java.util.Map;
Danke Xie22d1f9f2009-08-18 18:28:45 -040092import java.util.Map.Entry;
Jake Hambyb49a73d2011-03-15 20:09:46 -070093import java.util.Properties;
Yu-Han Yange7baef32018-02-09 13:58:17 -080094
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095/**
gomo4402af62017-01-11 13:20:13 -080096 * A GNSS implementation of LocationProvider used by LocationManager.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097 *
98 * {@hide}
99 */
Yu-Han Yang66c7ea92018-03-11 17:17:15 -0700100public class GnssLocationProvider implements LocationProviderInterface, InjectNtpTimeCallback,
101 GnssSatelliteBlacklistCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102
Lifu Tang30f95a72016-01-07 23:20:38 -0800103 private static final String TAG = "GnssLocationProvider";
Mike Lockwood29c84342009-05-06 14:01:15 -0400104
Brian Muramatsu1715cb32012-08-08 17:32:21 -0700105 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
106 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400107
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700108 private static final ProviderProperties PROPERTIES = new ProviderProperties(
109 true, true, false, false, true, true, true,
110 Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
111
gomo4402af62017-01-11 13:20:13 -0800112 // these need to match GnssPositionMode enum in IGnss.hal
The Android Open Source Project10592532009-03-18 17:39:46 -0700113 private static final int GPS_POSITION_MODE_STANDALONE = 0;
114 private static final int GPS_POSITION_MODE_MS_BASED = 1;
115 private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
116
gomo4402af62017-01-11 13:20:13 -0800117 // these need to match GnssPositionRecurrence enum in IGnss.hal
Mike Lockwood04598b62010-04-14 17:17:24 -0400118 private static final int GPS_POSITION_RECURRENCE_PERIODIC = 0;
119 private static final int GPS_POSITION_RECURRENCE_SINGLE = 1;
120
gomo4402af62017-01-11 13:20:13 -0800121 // these need to match GnssStatusValue enum in IGnssCallback.hal
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122 private static final int GPS_STATUS_NONE = 0;
123 private static final int GPS_STATUS_SESSION_BEGIN = 1;
124 private static final int GPS_STATUS_SESSION_END = 2;
125 private static final int GPS_STATUS_ENGINE_ON = 3;
126 private static final int GPS_STATUS_ENGINE_OFF = 4;
127
gomo4402af62017-01-11 13:20:13 -0800128 // these need to match GnssLocationFlags enum in types.hal
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 private static final int LOCATION_INVALID = 0;
130 private static final int LOCATION_HAS_LAT_LONG = 1;
131 private static final int LOCATION_HAS_ALTITUDE = 2;
132 private static final int LOCATION_HAS_SPEED = 4;
133 private static final int LOCATION_HAS_BEARING = 8;
gomo4402af62017-01-11 13:20:13 -0800134 private static final int LOCATION_HAS_HORIZONTAL_ACCURACY = 16;
135 private static final int LOCATION_HAS_VERTICAL_ACCURACY = 32;
136 private static final int LOCATION_HAS_SPEED_ACCURACY = 64;
137 private static final int LOCATION_HAS_BEARING_ACCURACY = 128;
Mike Lockwoode3635c92009-05-11 08:38:02 -0400138
gomo4402af62017-01-11 13:20:13 -0800139
140 // IMPORTANT - the GPS_DELETE_* symbols here must match GnssAidingData enum in IGnss.hal
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 private static final int GPS_DELETE_EPHEMERIS = 0x0001;
142 private static final int GPS_DELETE_ALMANAC = 0x0002;
143 private static final int GPS_DELETE_POSITION = 0x0004;
144 private static final int GPS_DELETE_TIME = 0x0008;
145 private static final int GPS_DELETE_IONO = 0x0010;
146 private static final int GPS_DELETE_UTC = 0x0020;
147 private static final int GPS_DELETE_HEALTH = 0x0040;
148 private static final int GPS_DELETE_SVDIR = 0x0080;
149 private static final int GPS_DELETE_SVSTEER = 0x0100;
150 private static final int GPS_DELETE_SADATA = 0x0200;
151 private static final int GPS_DELETE_RTI = 0x0400;
152 private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
153 private static final int GPS_DELETE_ALL = 0xFFFF;
154
gomo4402af62017-01-11 13:20:13 -0800155 // The GPS_CAPABILITY_* flags must match Capabilities enum in IGnssCallback.hal
Mike Lockwood04598b62010-04-14 17:17:24 -0400156 private static final int GPS_CAPABILITY_SCHEDULING = 0x0000001;
157 private static final int GPS_CAPABILITY_MSB = 0x0000002;
158 private static final int GPS_CAPABILITY_MSA = 0x0000004;
159 private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400160 private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010;
destradaa6568d702014-10-27 12:47:41 -0700161 private static final int GPS_CAPABILITY_GEOFENCING = 0x0000020;
162 private static final int GPS_CAPABILITY_MEASUREMENTS = 0x0000040;
163 private static final int GPS_CAPABILITY_NAV_MESSAGES = 0x0000080;
Mike Lockwood04598b62010-04-14 17:17:24 -0400164
Tsuwei Chen462bcd82014-09-17 12:28:49 -0700165 // The AGPS SUPL mode
166 private static final int AGPS_SUPL_MODE_MSA = 0x02;
167 private static final int AGPS_SUPL_MODE_MSB = 0x01;
168
gomo4402af62017-01-11 13:20:13 -0800169 // these need to match AGnssType enum in IAGnssCallback.hal
Mike Lockwoode3635c92009-05-11 08:38:02 -0400170 private static final int AGPS_TYPE_SUPL = 1;
171 private static final int AGPS_TYPE_C2K = 2;
172
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400173 // Handler messages
174 private static final int CHECK_LOCATION = 1;
175 private static final int ENABLE = 2;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700176 private static final int SET_REQUEST = 3;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400177 private static final int UPDATE_NETWORK_STATE = 4;
178 private static final int INJECT_NTP_TIME = 5;
179 private static final int DOWNLOAD_XTRA_DATA = 6;
Wyatt Rileyc7067412018-02-07 15:50:35 -0800180 private static final int UPDATE_LOCATION = 7; // Handle external location from network listener
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400181 private static final int ADD_LISTENER = 8;
182 private static final int REMOVE_LISTENER = 9;
Kevin Tang40e1baf2012-01-10 14:32:44 -0800183 private static final int DOWNLOAD_XTRA_DATA_FINISHED = 11;
destradaafb23c672015-04-16 14:01:27 -0700184 private static final int SUBSCRIPTION_OR_SIM_CHANGED = 12;
185 private static final int INITIALIZE_HANDLER = 13;
destradaae21252a2015-09-08 12:32:59 -0700186 private static final int REQUEST_SUPL_CONNECTION = 14;
187 private static final int RELEASE_SUPL_CONNECTION = 15;
Yu-Han Yange7baef32018-02-09 13:58:17 -0800188 private static final int REQUEST_LOCATION = 16;
Wyatt Riley26465d22018-02-12 13:44:24 -0800189 private static final int REPORT_LOCATION = 17; // HAL reports location
190 private static final int REPORT_SV_STATUS = 18; // HAL reports SV status
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400191
Miguel Torroja1e84da82010-07-27 07:02:24 +0200192 // Request setid
193 private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
194 private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2;
195
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700196 //TODO(b/33112647): Create gps_debug.conf with commented career parameters.
197 private static final String DEBUG_PROPERTIES_FILE = "/etc/gps_debug.conf";
Miguel Torroja1e84da82010-07-27 07:02:24 +0200198
199 // ref. location info
200 private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
201 private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
Miguel Torroja1e84da82010-07-27 07:02:24 +0200202
203 // set id info
204 private static final int AGPS_SETID_TYPE_NONE = 0;
205 private static final int AGPS_SETID_TYPE_IMSI = 1;
206 private static final int AGPS_SETID_TYPE_MSISDN = 2;
207
gomo48f1a642017-11-10 20:35:46 -0800208 private static final int GPS_GEOFENCE_UNAVAILABLE = 1 << 0L;
209 private static final int GPS_GEOFENCE_AVAILABLE = 1 << 1L;
destradaa0682809a2013-08-12 18:50:30 -0700210
gomo4402af62017-01-11 13:20:13 -0800211 // GPS Geofence errors. Should match GeofenceStatus enum in IGnssGeofenceCallback.hal.
destradaa0682809a2013-08-12 18:50:30 -0700212 private static final int GPS_GEOFENCE_OPERATION_SUCCESS = 0;
213 private static final int GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES = 100;
gomo48f1a642017-11-10 20:35:46 -0800214 private static final int GPS_GEOFENCE_ERROR_ID_EXISTS = -101;
destradaa0682809a2013-08-12 18:50:30 -0700215 private static final int GPS_GEOFENCE_ERROR_ID_UNKNOWN = -102;
216 private static final int GPS_GEOFENCE_ERROR_INVALID_TRANSITION = -103;
217 private static final int GPS_GEOFENCE_ERROR_GENERIC = -149;
218
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700219 // TCP/IP constants.
220 // Valid TCP/UDP port range is (0, 65535].
221 private static final int TCP_MIN_PORT = 0;
222 private static final int TCP_MAX_PORT = 0xffff;
223
Yu-Han Yange7baef32018-02-09 13:58:17 -0800224 // 1 second, or 1 Hz frequency.
225 private static final long LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS = 1000;
Yu-Han Yang639f7592018-06-07 11:58:52 -0700226 // Default update duration in milliseconds for REQUEST_LOCATION.
Yu-Han Yang9e2a8232018-06-14 12:10:08 -0700227 private static final long LOCATION_UPDATE_DURATION_MILLIS = 10 * 1000;
Yu-Han Yange7baef32018-02-09 13:58:17 -0800228
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700229 /** simpler wrapper for ProviderRequest + Worksource */
230 private static class GpsRequest {
231 public ProviderRequest request;
232 public WorkSource source;
gomo48f1a642017-11-10 20:35:46 -0800233
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700234 public GpsRequest(ProviderRequest request, WorkSource source) {
235 this.request = request;
236 this.source = source;
237 }
238 }
239
Wyatt Riley26465d22018-02-12 13:44:24 -0800240 // Threadsafe class to hold stats reported in the Extras Bundle
Wyatt Rileyc7067412018-02-07 15:50:35 -0800241 private static class LocationExtras {
242 private int mSvCount;
243 private int mMeanCn0;
244 private int mMaxCn0;
245 private final Bundle mBundle;
246
247 public LocationExtras() {
248 mBundle = new Bundle();
249 }
250
251 public void set(int svCount, int meanCn0, int maxCn0) {
Wyatt Riley26465d22018-02-12 13:44:24 -0800252 synchronized(this) {
253 mSvCount = svCount;
254 mMeanCn0 = meanCn0;
255 mMaxCn0 = maxCn0;
256 }
Wyatt Rileyc7067412018-02-07 15:50:35 -0800257 setBundle(mBundle);
258 }
259
260 public void reset() {
261 set(0,0,0);
262 }
263
264 // Also used by outside methods to add to other bundles
265 public void setBundle(Bundle extras) {
266 if (extras != null) {
Wyatt Riley26465d22018-02-12 13:44:24 -0800267 synchronized (this) {
268 extras.putInt("satellites", mSvCount);
269 extras.putInt("meanCn0", mMeanCn0);
270 extras.putInt("maxCn0", mMaxCn0);
271 }
Wyatt Rileyc7067412018-02-07 15:50:35 -0800272 }
273 }
274
275 public Bundle getBundle() {
Wyatt Riley26465d22018-02-12 13:44:24 -0800276 synchronized (this) {
277 return new Bundle(mBundle);
278 }
Wyatt Rileyc7067412018-02-07 15:50:35 -0800279 }
280 }
281
Yu-Han Yang66c7ea92018-03-11 17:17:15 -0700282 private final Object mLock = new Object();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284 // current status
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400285 private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286
287 // time for last status update
288 private long mStatusUpdateTime = SystemClock.elapsedRealtime();
Mike Lockwoodd53ba012010-04-15 20:41:26 -0400289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 // turn off GPS fix icon if we haven't received a fix in 10 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400291 private static final long RECENT_FIX_TIMEOUT = 10 * 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292
Mike Lockwood0632ca72009-05-14 15:51:03 -0400293 // stop trying if we do not receive a fix within 60 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400294 private static final int NO_FIX_TIMEOUT = 60 * 1000;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400295
Nick Pellyb041f232012-05-07 17:12:25 -0700296 // if the fix interval is below this we leave GPS on,
297 // if above then we cycle the GPS driver.
298 // Typical hot TTTF is ~5 seconds, so 10 seconds seems sane.
299 private static final int GPS_POLLING_THRESHOLD_INTERVAL = 10 * 1000;
300
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700301 // how long to wait if we have a network error in NTP or XTRA downloading
Wei Liu6f6326b2015-06-24 23:47:50 -0700302 // the initial value of the exponential backoff
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700303 // current setting - 5 minutes
gomo48f1a642017-11-10 20:35:46 -0800304 private static final long RETRY_INTERVAL = 5 * 60 * 1000;
Wei Liu6f6326b2015-06-24 23:47:50 -0700305 // how long to wait if we have a network error in NTP or XTRA downloading
306 // the max value of the exponential backoff
307 // current setting - 4 hours
gomo48f1a642017-11-10 20:35:46 -0800308 private static final long MAX_RETRY_INTERVAL = 4 * 60 * 60 * 1000;
Wei Liu6f6326b2015-06-24 23:47:50 -0700309
Wei Wangc5706f62017-04-18 11:26:26 -0700310 // Timeout when holding wakelocks for downloading XTRA data.
311 private static final long DOWNLOAD_XTRA_DATA_TIMEOUT_MS = 60 * 1000;
312
Yu-Han Yanga1862b52018-02-20 17:05:59 -0800313 private final ExponentialBackOff mXtraBackOff = new ExponentialBackOff(RETRY_INTERVAL,
314 MAX_RETRY_INTERVAL);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700315
316 // true if we are enabled, protected by this
317 private boolean mEnabled;
318
Kevin Tang40e1baf2012-01-10 14:32:44 -0800319 // states for injecting ntp and downloading xtra data
320 private static final int STATE_PENDING_NETWORK = 0;
321 private static final int STATE_DOWNLOADING = 1;
322 private static final int STATE_IDLE = 2;
323
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400324 // flags to trigger NTP or XTRA data download when network becomes available
325 // initialized to true so we do NTP and XTRA when the network comes up after booting
Kevin Tang40e1baf2012-01-10 14:32:44 -0800326 private int mDownloadXtraDataPending = STATE_PENDING_NETWORK;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 // true if GPS is navigating
329 private boolean mNavigating;
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -0500330
331 // true if GPS engine is on
332 private boolean mEngineOn;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700333
Mike Lockwood04598b62010-04-14 17:17:24 -0400334 // requested frequency of fixes, in milliseconds
335 private int mFixInterval = 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336
gomo48f1a642017-11-10 20:35:46 -0800337 // true if low power mode for the GNSS chipset is part of the latest request.
338 private boolean mLowPowerMode = false;
339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800340 // true if we started navigation
341 private boolean mStarted;
342
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -0700343 // true if single shot request is in progress
344 private boolean mSingleShot;
345
Mike Lockwood04598b62010-04-14 17:17:24 -0400346 // capabilities of the GPS engine
347 private int mEngineCapabilities;
348
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -0400349 // true if XTRA is supported
350 private boolean mSupportsXtra;
351
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800352 // for calculating time to first fix
353 private long mFixRequestTime = 0;
354 // time to first fix for most recent session
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700355 private int mTimeToFirstFix = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356 // time we received our last fix
357 private long mLastFixTime;
358
Mike Lockwood04598b62010-04-14 17:17:24 -0400359 private int mPositionMode;
Yu-Han Yangc8b9ff72018-04-17 00:47:24 -0700360 private GnssPositionMode mLastPositionMode;
Mike Lockwood04598b62010-04-14 17:17:24 -0400361
David Christied4edf4c2014-08-12 15:22:27 -0700362 // Current request from underlying location clients.
363 private ProviderRequest mProviderRequest = null;
Narayan Kamath32684dd2018-01-08 17:32:51 +0000364 // The WorkSource associated with the most recent client request (i.e, most recent call to
365 // setRequest).
David Christied4edf4c2014-08-12 15:22:27 -0700366 private WorkSource mWorkSource = null;
367 // True if gps should be disabled (used to support battery saver mode in settings).
368 private boolean mDisableGps = false;
369
destradaafb23c672015-04-16 14:01:27 -0700370 /**
371 * Properties loaded from PROPERTIES_FILE.
372 * It must be accessed only inside {@link #mHandler}.
373 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374 private Properties mProperties;
destradaafb23c672015-04-16 14:01:27 -0700375
Mike Lockwood734d6032009-07-28 18:30:25 -0700376 private String mSuplServerHost;
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700377 private int mSuplServerPort = TCP_MIN_PORT;
Mike Lockwood734d6032009-07-28 18:30:25 -0700378 private String mC2KServerHost;
379 private int mC2KServerPort;
Tsuwei Chen3324e952014-09-07 01:30:42 -0700380 private boolean mSuplEsEnabled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400382 private final Context mContext;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700383 private final ILocationManager mILocationManager;
Wyatt Rileyc7067412018-02-07 15:50:35 -0800384 private final LocationExtras mLocationExtras = new LocationExtras();
Lifu Tang30f95a72016-01-07 23:20:38 -0800385 private final GnssStatusListenerHelper mListenerHelper;
Yu-Han Yang66c7ea92018-03-11 17:17:15 -0700386 private final GnssSatelliteBlacklistHelper mGnssSatelliteBlacklistHelper;
Lifu Tang818aa2c2016-02-01 01:52:00 -0800387 private final GnssMeasurementsProvider mGnssMeasurementsProvider;
388 private final GnssNavigationMessageProvider mGnssNavigationMessageProvider;
Yu-Han Yang07561382018-02-21 13:08:37 -0800389 private final LocationChangeListener mNetworkLocationListener = new NetworkLocationListener();
390 private final LocationChangeListener mFusedLocationListener = new FusedLocationListener();
Yu-Han Yanga1862b52018-02-20 17:05:59 -0800391 private final NtpTimeHelper mNtpTimeHelper;
Yu-Han Yang3557cc72018-03-21 12:48:36 -0700392 private final GnssBatchingProvider mGnssBatchingProvider;
Yu-Han Yang890ca8b2018-04-16 22:11:31 -0700393 private final GnssGeofenceProvider mGnssGeofenceProvider;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400394
Victoria Lease5c24fd02012-10-01 11:00:50 -0700395 // Handler for processing events
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400396 private Handler mHandler;
The Android Open Source Project10592532009-03-18 17:39:46 -0700397
Anil Admal50ba15e2018-11-01 16:42:42 -0700398 private final GnssNetworkConnectivityHandler mNetworkConnectivityHandler;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700399 private final GpsNetInitiatedHandler mNIHandler;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400400
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400401 // Wakelocks
Lifu Tang30f95a72016-01-07 23:20:38 -0800402 private final static String WAKELOCK_KEY = "GnssLocationProvider";
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400403 private final PowerManager.WakeLock mWakeLock;
Wei Wangb71c0492017-05-01 20:24:19 -0700404 private static final String DOWNLOAD_EXTRA_WAKELOCK_KEY = "GnssLocationProviderXtraDownload";
405 private final PowerManager.WakeLock mDownloadXtraWakeLock;
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400406
Mike Lockwood29c84342009-05-06 14:01:15 -0400407 // Alarms
408 private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
Mike Lockwood0632ca72009-05-14 15:51:03 -0400409 private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700410
411 // SIM/Carrier info.
412 private final static String SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
413
Ecco Park624ac3c2016-07-18 14:08:05 -0700414 // Persist property for LPP_PROFILE
415 private final static String LPP_PROFILE = "persist.sys.gps.lpp";
416
Ecco Park624ac3c2016-07-18 14:08:05 -0700417
David Christied4edf4c2014-08-12 15:22:27 -0700418 private final PowerManager mPowerManager;
Mike Lockwood29c84342009-05-06 14:01:15 -0400419 private final AlarmManager mAlarmManager;
420 private final PendingIntent mWakeupIntent;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400421 private final PendingIntent mTimeoutIntent;
Mike Lockwood29c84342009-05-06 14:01:15 -0400422
Svet Ganovf7b47252018-02-26 11:11:27 -0800423 private final AppOpsManager mAppOps;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400424 private final IBatteryStats mBatteryStats;
The Android Open Source Project10592532009-03-18 17:39:46 -0700425
Narayan Kamath32684dd2018-01-08 17:32:51 +0000426 // Current list of underlying location clients.
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700427 // only modified on handler thread
Dianne Hackborn002a54e2013-01-10 17:34:55 -0800428 private WorkSource mClientSource = new WorkSource();
Mike Lockwoodf1218be2010-01-29 09:20:06 -0500429
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700430 private GeofenceHardwareImpl mGeofenceHardwareImpl;
Wyatt Rileyd87cf912017-12-05 09:31:52 -0800431
432 // Volatile for simple inter-thread sync on these values.
433 private volatile int mHardwareYear = 0;
Wyatt Riley49097c02018-03-15 09:14:43 -0700434 private volatile String mHardwareModelName;
Lifu Tang82f893d2016-01-21 18:15:33 -0800435
Wyatt Riley5d5bac82016-11-01 07:05:16 -0700436 // Set lower than the current ITAR limit of 600m/s to allow this to trigger even if GPS HAL
437 // stops output right at 600m/s, depriving this of the information of a device that reaches
438 // greater than 600m/s, and higher than the speed of sound to avoid impacting most use cases.
439 private static final float ITAR_SPEED_LIMIT_METERS_PER_SECOND = 400.0F;
Wyatt Riley042c48f2017-10-06 14:59:25 -0700440
Wyatt Riley042c48f2017-10-06 14:59:25 -0700441 private volatile boolean mItarSpeedLimitExceeded = false;
Wyatt Riley5d5bac82016-11-01 07:05:16 -0700442
Siddharth Raybb608c82017-03-16 11:33:34 -0700443 // GNSS Metrics
444 private GnssMetrics mGnssMetrics;
445
Lifu Tang30f95a72016-01-07 23:20:38 -0800446 private final IGnssStatusProvider mGnssStatusProvider = new IGnssStatusProvider.Stub() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700447 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -0800448 public void registerGnssStatusCallback(IGnssStatusListener callback) {
449 mListenerHelper.addListener(callback);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400450 }
451
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700452 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -0800453 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
454 mListenerHelper.removeListener(callback);
destradaaea8a8a62014-06-23 18:19:03 -0700455 }
456 };
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400457
Lifu Tang30f95a72016-01-07 23:20:38 -0800458 public IGnssStatusProvider getGnssStatusProvider() {
459 return mGnssStatusProvider;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400460 }
461
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700462 public IGpsGeofenceHardware getGpsGeofenceProxy() {
Yu-Han Yang890ca8b2018-04-16 22:11:31 -0700463 return mGnssGeofenceProvider;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700464 }
465
Lifu Tang818aa2c2016-02-01 01:52:00 -0800466 public GnssMeasurementsProvider getGnssMeasurementsProvider() {
467 return mGnssMeasurementsProvider;
destradaaea8a8a62014-06-23 18:19:03 -0700468 }
469
Lifu Tang818aa2c2016-02-01 01:52:00 -0800470 public GnssNavigationMessageProvider getGnssNavigationMessageProvider() {
471 return mGnssNavigationMessageProvider;
destradaa4b3e3932014-07-21 18:01:47 -0700472 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700473 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
gomo48f1a642017-11-10 20:35:46 -0800474 @Override
475 public void onReceive(Context context, Intent intent) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700476 String action = intent.getAction();
Tsuwei Chen48d37f92014-09-05 15:15:34 -0700477 if (DEBUG) Log.d(TAG, "receive broadcast intent, action: " + action);
destradaaee9fd342015-08-31 13:31:17 -0700478 if (action == null) {
479 return;
480 }
481
Mike Lockwood29c84342009-05-06 14:01:15 -0400482 if (action.equals(ALARM_WAKEUP)) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -0700483 startNavigating(false);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400484 } else if (action.equals(ALARM_TIMEOUT)) {
Mike Lockwood0632ca72009-05-14 15:51:03 -0400485 hibernate();
David Christied4edf4c2014-08-12 15:22:27 -0700486 } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)
Adam Lesinski87c17df2015-05-27 13:24:13 -0700487 || PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)
David Christied4edf4c2014-08-12 15:22:27 -0700488 || Intent.ACTION_SCREEN_OFF.equals(action)
489 || Intent.ACTION_SCREEN_ON.equals(action)) {
490 updateLowPowerMode();
Wink Savillea374c3d2014-11-11 11:48:04 -0800491 } else if (action.equals(SIM_STATE_CHANGED)) {
492 subscriptionOrSimChanged(context);
David Christied4edf4c2014-08-12 15:22:27 -0700493 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700494 }
Mike Lockwood29c84342009-05-06 14:01:15 -0400495 };
The Android Open Source Project10592532009-03-18 17:39:46 -0700496
Wink Savilled09c4ca2014-11-22 10:08:16 -0800497 private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
498 new OnSubscriptionsChangedListener() {
gomo48f1a642017-11-10 20:35:46 -0800499 @Override
500 public void onSubscriptionsChanged() {
501 sendMessage(SUBSCRIPTION_OR_SIM_CHANGED, 0, null);
502 }
503 };
Wink Savillea374c3d2014-11-11 11:48:04 -0800504
Yu-Han Yang66c7ea92018-03-11 17:17:15 -0700505 /**
506 * Implements {@link GnssSatelliteBlacklistCallback#onUpdateSatelliteBlacklist}.
507 */
508 @Override
509 public void onUpdateSatelliteBlacklist(int[] constellations, int[] svids) {
510 mHandler.post(()->{
511 native_set_satellite_blacklist(constellations, svids);
512 });
513 }
514
Wink Savillea374c3d2014-11-11 11:48:04 -0800515 private void subscriptionOrSimChanged(Context context) {
Joe Onorato0c484102016-02-01 18:04:24 -0800516 if (DEBUG) Log.d(TAG, "received SIM related action: ");
Wink Savillea374c3d2014-11-11 11:48:04 -0800517 TelephonyManager phone = (TelephonyManager)
518 mContext.getSystemService(Context.TELEPHONY_SERVICE);
Ecco Park4fa1ab72016-10-24 13:04:52 -0700519 CarrierConfigManager configManager = (CarrierConfigManager)
520 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Wink Savillea374c3d2014-11-11 11:48:04 -0800521 String mccMnc = phone.getSimOperator();
Ecco Park4fa1ab72016-10-24 13:04:52 -0700522 boolean isKeepLppProfile = false;
Wink Savillea374c3d2014-11-11 11:48:04 -0800523 if (!TextUtils.isEmpty(mccMnc)) {
Joe Onorato0c484102016-02-01 18:04:24 -0800524 if (DEBUG) Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc);
Wink Savillea374c3d2014-11-11 11:48:04 -0800525 synchronized (mLock) {
Ecco Park4fa1ab72016-10-24 13:04:52 -0700526 if (configManager != null) {
527 PersistableBundle b = configManager.getConfig();
Wyatt Rileya8ce2252017-09-01 13:31:17 -0700528 if (b != null) {
529 isKeepLppProfile =
530 b.getBoolean(CarrierConfigManager.KEY_PERSIST_LPP_MODE_BOOL);
531 }
Ecco Park4fa1ab72016-10-24 13:04:52 -0700532 }
533 if (isKeepLppProfile) {
534 // load current properties for the carrier
535 loadPropertiesFromResource(context, mProperties);
536 String lpp_profile = mProperties.getProperty("LPP_PROFILE");
537 // set the persist property LPP_PROFILE for the value
Ecco Park8eec7442017-08-04 16:21:59 -0700538 if (lpp_profile != null) {
539 SystemProperties.set(LPP_PROFILE, lpp_profile);
540 }
Ecco Park624ac3c2016-07-18 14:08:05 -0700541 } else {
Ecco Park4fa1ab72016-10-24 13:04:52 -0700542 // reset the persist property
543 SystemProperties.set(LPP_PROFILE, "");
Ecco Park624ac3c2016-07-18 14:08:05 -0700544 }
Wink Savillea374c3d2014-11-11 11:48:04 -0800545 reloadGpsProperties(context, mProperties);
546 mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
547 }
548 } else {
Joe Onorato0c484102016-02-01 18:04:24 -0800549 if (DEBUG) Log.d(TAG, "SIM MCC/MNC is still not available");
Wink Savillea374c3d2014-11-11 11:48:04 -0800550 }
551 }
552
David Christied4edf4c2014-08-12 15:22:27 -0700553 private void updateLowPowerMode() {
Adam Lesinski87c17df2015-05-27 13:24:13 -0700554 // Disable GPS if we are in device idle mode.
555 boolean disableGps = mPowerManager.isDeviceIdleMode();
jackqdyulei455e90a2017-02-09 15:29:16 -0800556 final PowerSaveState result =
557 mPowerManager.getPowerSaveState(ServiceType.GPS);
558 switch (result.gpsMode) {
Makoto Onuki57f0f552017-12-11 12:22:18 -0800559 case PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF:
Adam Lesinski87c17df2015-05-27 13:24:13 -0700560 // If we are in battery saver mode and the screen is off, disable GPS.
jackqdyulei455e90a2017-02-09 15:29:16 -0800561 disableGps |= result.batterySaverEnabled && !mPowerManager.isInteractive();
David Christied4edf4c2014-08-12 15:22:27 -0700562 break;
David Christied4edf4c2014-08-12 15:22:27 -0700563 }
564 if (disableGps != mDisableGps) {
565 mDisableGps = disableGps;
566 updateRequirements();
567 }
568 }
569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570 public static boolean isSupported() {
571 return native_is_supported();
572 }
573
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700574 interface SetCarrierProperty {
575 public boolean set(int value);
576 }
577
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700578 private void reloadGpsProperties(Context context, Properties properties) {
Joe Onorato0c484102016-02-01 18:04:24 -0800579 if (DEBUG) Log.d(TAG, "Reset GPS properties, previous size = " + properties.size());
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700580 loadPropertiesFromResource(context, properties);
Ecco Park624ac3c2016-07-18 14:08:05 -0700581
Ecco Park624ac3c2016-07-18 14:08:05 -0700582 String lpp_prof = SystemProperties.get(LPP_PROFILE);
583 if (!TextUtils.isEmpty(lpp_prof)) {
gomo48f1a642017-11-10 20:35:46 -0800584 // override default value of this if lpp_prof is not empty
585 properties.setProperty("LPP_PROFILE", lpp_prof);
Ecco Park624ac3c2016-07-18 14:08:05 -0700586 }
Wyatt Riley3e1cd0b2017-04-19 17:57:14 -0700587 /*
588 * Overlay carrier properties from a debug configuration file.
589 */
590 loadPropertiesFromFile(DEBUG_PROPERTIES_FILE, properties);
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700591 // TODO: we should get rid of C2K specific setting.
592 setSuplHostPort(properties.getProperty("SUPL_HOST"),
gomo48f1a642017-11-10 20:35:46 -0800593 properties.getProperty("SUPL_PORT"));
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700594 mC2KServerHost = properties.getProperty("C2K_HOST");
595 String portString = properties.getProperty("C2K_PORT");
596 if (mC2KServerHost != null && portString != null) {
597 try {
598 mC2KServerPort = Integer.parseInt(portString);
599 } catch (NumberFormatException e) {
600 Log.e(TAG, "unable to parse C2K_PORT: " + portString);
601 }
602 }
destradaaef752b62015-04-17 13:10:47 -0700603 if (native_is_gnss_configuration_supported()) {
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700604 Map<String, SetCarrierProperty> map = new HashMap<String, SetCarrierProperty>() {
605 {
606 put("SUPL_VER", (val) -> native_set_supl_version(val));
607 put("SUPL_MODE", (val) -> native_set_supl_mode(val));
608 put("SUPL_ES", (val) -> native_set_supl_es(val));
609 put("LPP_PROFILE", (val) -> native_set_lpp_profile(val));
gomo48f1a642017-11-10 20:35:46 -0800610 put("A_GLONASS_POS_PROTOCOL_SELECT",
611 (val) -> native_set_gnss_pos_protocol_select(val));
612 put("USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL",
613 (val) -> native_set_emergency_supl_pdn(val));
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700614 put("GPS_LOCK", (val) -> native_set_gps_lock(val));
615 }
616 };
617
gomo48f1a642017-11-10 20:35:46 -0800618 for (Entry<String, SetCarrierProperty> entry : map.entrySet()) {
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700619 String propertyName = entry.getKey();
620 String propertyValueString = properties.getProperty(propertyName);
621 if (propertyValueString != null) {
622 try {
gomo48f1a642017-11-10 20:35:46 -0800623 int propertyValueInt = Integer.decode(propertyValueString);
624 boolean result = entry.getValue().set(propertyValueInt);
625 if (result == false) {
626 Log.e(TAG, "Unable to set " + propertyName);
627 }
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700628 } catch (NumberFormatException e) {
gomo48f1a642017-11-10 20:35:46 -0800629 Log.e(TAG, "unable to parse propertyName: " + propertyValueString);
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700630 }
631 }
destradaaef752b62015-04-17 13:10:47 -0700632 }
633 } else if (DEBUG) {
634 Log.d(TAG, "Skipped configuration update because GNSS configuration in GPS HAL is not"
635 + " supported");
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700636 }
Tsuwei Chen3324e952014-09-07 01:30:42 -0700637
638 // SUPL_ES configuration.
639 String suplESProperty = mProperties.getProperty("SUPL_ES");
640 if (suplESProperty != null) {
641 try {
642 mSuplEsEnabled = (Integer.parseInt(suplESProperty) == 1);
643 } catch (NumberFormatException e) {
644 Log.e(TAG, "unable to parse SUPL_ES: " + suplESProperty);
645 }
646 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700647 }
648
649 private void loadPropertiesFromResource(Context context,
gomo48f1a642017-11-10 20:35:46 -0800650 Properties properties) {
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700651 String[] configValues = context.getResources().getStringArray(
652 com.android.internal.R.array.config_gpsParameters);
653 for (String item : configValues) {
Joe Onorato0c484102016-02-01 18:04:24 -0800654 if (DEBUG) Log.d(TAG, "GpsParamsResource: " + item);
Tsuwei Chen7c485bf2014-09-10 15:33:34 -0700655 // We need to support "KEY =", but not "=VALUE".
Zheng Zhangad48bd92017-10-16 10:27:28 -0700656 int index = item.indexOf("=");
657 if (index > 0 && index + 1 < item.length()) {
658 String key = item.substring(0, index);
659 String value = item.substring(index + 1);
660 properties.setProperty(key.trim().toUpperCase(), value);
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700661 } else {
662 Log.w(TAG, "malformed contents: " + item);
663 }
664 }
665 }
666
667 private boolean loadPropertiesFromFile(String filename,
gomo48f1a642017-11-10 20:35:46 -0800668 Properties properties) {
Colin Cross7c030ed2014-01-28 09:33:53 -0800669 try {
670 File file = new File(filename);
671 FileInputStream stream = null;
672 try {
673 stream = new FileInputStream(file);
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700674 properties.load(stream);
Colin Cross7c030ed2014-01-28 09:33:53 -0800675 } finally {
676 IoUtils.closeQuietly(stream);
677 }
678
Colin Cross7c030ed2014-01-28 09:33:53 -0800679 } catch (IOException e) {
Wyatt Riley3e1cd0b2017-04-19 17:57:14 -0700680 if (DEBUG) Log.d(TAG, "Could not open GPS configuration file " + filename);
Colin Cross7c030ed2014-01-28 09:33:53 -0800681 return false;
682 }
683 return true;
684 }
685
Lifu Tang30f95a72016-01-07 23:20:38 -0800686 public GnssLocationProvider(Context context, ILocationManager ilocationManager,
Victoria Lease5cd731a2012-12-19 15:04:21 -0800687 Looper looper) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800688 mContext = context;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700689 mILocationManager = ilocationManager;
Mike Lockwood63598a02010-02-24 11:52:59 -0500690
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400691 // Create a wake lock
David Christied4edf4c2014-08-12 15:22:27 -0700692 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
693 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700694 mWakeLock.setReferenceCounted(true);
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400695
Wei Wangb71c0492017-05-01 20:24:19 -0700696 // Create a separate wake lock for xtra downloader as it may be released due to timeout.
697 mDownloadXtraWakeLock = mPowerManager.newWakeLock(
698 PowerManager.PARTIAL_WAKE_LOCK, DOWNLOAD_EXTRA_WAKELOCK_KEY);
699 mDownloadXtraWakeLock.setReferenceCounted(true);
700
gomo48f1a642017-11-10 20:35:46 -0800701 mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
Mike Lockwood29c84342009-05-06 14:01:15 -0400702 mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400703 mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
Mike Lockwood29c84342009-05-06 14:01:15 -0400704
Anil Admal50ba15e2018-11-01 16:42:42 -0700705 mNetworkConnectivityHandler = new GnssNetworkConnectivityHandler(
706 context,
707 GnssLocationProvider.this::onNetworkAvailable,
708 looper);
Mike Lockwood58bda982009-04-14 16:25:07 -0400709
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800710 // App ops service to keep track of who is accessing the GPS
Svet Ganovf7b47252018-02-26 11:11:27 -0800711 mAppOps = mContext.getSystemService(AppOpsManager.class);
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800712
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400713 // Battery statistics service to be notified when GPS turns on or off
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700714 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
715 BatteryStats.SERVICE_NAME));
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400716
destradaafb23c672015-04-16 14:01:27 -0700717 // Construct internal handler
718 mHandler = new ProviderHandler(looper);
719
720 // Load GPS configuration and register listeners in the background:
721 // some operations, such as opening files and registering broadcast receivers, can take a
722 // relative long time, so the ctor() is kept to create objects needed by this instance,
723 // while IO initialization and registration is delegated to our internal handler
724 // this approach is just fine because events are posted to our handler anyway
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700725 mProperties = new Properties();
destradaafb23c672015-04-16 14:01:27 -0700726 sendMessage(INITIALIZE_HANDLER, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400727
Tsuwei Chen3324e952014-09-07 01:30:42 -0700728 // Create a GPS net-initiated handler.
729 mNIHandler = new GpsNetInitiatedHandler(context,
gomo48f1a642017-11-10 20:35:46 -0800730 mNetInitiatedListener,
731 mSuplEsEnabled);
Tsuwei Chen3324e952014-09-07 01:30:42 -0700732
Lifu Tang30f95a72016-01-07 23:20:38 -0800733 mListenerHelper = new GnssStatusListenerHelper(mHandler) {
destradaa6568d702014-10-27 12:47:41 -0700734 @Override
735 protected boolean isAvailableInPlatform() {
destradaa13a60b02015-01-15 18:36:01 -0800736 return isSupported();
destradaa6568d702014-10-27 12:47:41 -0700737 }
738
739 @Override
740 protected boolean isGpsEnabled() {
741 return isEnabled();
742 }
743 };
744
Yu-Han Yang8de21502018-04-23 01:40:25 -0700745 mGnssMeasurementsProvider = new GnssMeasurementsProvider(mContext, mHandler) {
destradaa6568d702014-10-27 12:47:41 -0700746 @Override
747 protected boolean isGpsEnabled() {
748 return isEnabled();
749 }
750 };
751
Lifu Tang818aa2c2016-02-01 01:52:00 -0800752 mGnssNavigationMessageProvider = new GnssNavigationMessageProvider(mHandler) {
destradaa6568d702014-10-27 12:47:41 -0700753 @Override
destradaa6568d702014-10-27 12:47:41 -0700754 protected boolean isGpsEnabled() {
755 return isEnabled();
756 }
757 };
Yu-Han Yanga1862b52018-02-20 17:05:59 -0800758
Anil Admal50ba15e2018-11-01 16:42:42 -0700759 mGnssMetrics = new GnssMetrics(mBatteryStats);
Yu-Han Yang66c7ea92018-03-11 17:17:15 -0700760 mNtpTimeHelper = new NtpTimeHelper(mContext, looper, this);
761 mGnssSatelliteBlacklistHelper = new GnssSatelliteBlacklistHelper(mContext,
762 looper, this);
763 mHandler.post(mGnssSatelliteBlacklistHelper::updateSatelliteBlacklist);
Yu-Han Yang3557cc72018-03-21 12:48:36 -0700764 mGnssBatchingProvider = new GnssBatchingProvider();
Yu-Han Yang890ca8b2018-04-16 22:11:31 -0700765 mGnssGeofenceProvider = new GnssGeofenceProvider(looper);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400766 }
767
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800768 /**
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500769 * Returns the name of this provider.
770 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700771 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500772 public String getName() {
773 return LocationManager.GPS_PROVIDER;
774 }
775
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700776 @Override
777 public ProviderProperties getProperties() {
778 return PROPERTIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779 }
780
Yu-Han Yanga1862b52018-02-20 17:05:59 -0800781 /**
782 * Implements {@link InjectNtpTimeCallback#injectTime}
783 */
784 @Override
785 public void injectTime(long time, long timeReference, int uncertainty) {
786 native_inject_time(time, timeReference, uncertainty);
787 }
788
Anil Admal50ba15e2018-11-01 16:42:42 -0700789 /**
790 * Implements {@link GnssNetworkConnectivityHandler.GnssNetworkListener#onNetworkAvailable()}
791 */
792 private void onNetworkAvailable() {
793 mNtpTimeHelper.onNetworkAvailable();
794 if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
795 if (mSupportsXtra) {
796 // Download only if supported, (prevents an unneccesary on-boot
797 // download)
798 xtraDownloadRequest();
destradaaef752b62015-04-17 13:10:47 -0700799 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400800 }
801 }
Yu-Han Yang8de21502018-04-23 01:40:25 -0700802
Yu-Han Yange7baef32018-02-09 13:58:17 -0800803 private void handleRequestLocation(boolean independentFromGnss) {
804 if (isRequestLocationRateLimited()) {
805 if (DEBUG) {
806 Log.d(TAG, "RequestLocation is denied due to too frequent requests.");
807 }
808 return;
809 }
Yu-Han Yang74041ff2018-04-06 15:57:31 -0700810 ContentResolver resolver = mContext.getContentResolver();
811 long durationMillis = Settings.Global.getLong(
812 resolver,
813 Settings.Global.GNSS_HAL_LOCATION_REQUEST_DURATION_MILLIS,
814 LOCATION_UPDATE_DURATION_MILLIS);
815 if (durationMillis == 0) {
816 Log.i(TAG, "GNSS HAL location request is disabled by Settings.");
817 return;
818 }
Yu-Han Yange7baef32018-02-09 13:58:17 -0800819
820 LocationManager locationManager = (LocationManager) mContext.getSystemService(
821 Context.LOCATION_SERVICE);
Yu-Han Yang07561382018-02-21 13:08:37 -0800822 String provider;
823 LocationChangeListener locationListener;
Yu-Han Yange7baef32018-02-09 13:58:17 -0800824
825 if (independentFromGnss) {
826 // For fast GNSS TTFF
Yu-Han Yang07561382018-02-21 13:08:37 -0800827 provider = LocationManager.NETWORK_PROVIDER;
828 locationListener = mNetworkLocationListener;
Yu-Han Yange7baef32018-02-09 13:58:17 -0800829 } else {
830 // For Device-Based Hybrid (E911)
Yu-Han Yang07561382018-02-21 13:08:37 -0800831 provider = LocationManager.FUSED_PROVIDER;
832 locationListener = mFusedLocationListener;
Yu-Han Yange7baef32018-02-09 13:58:17 -0800833 }
Yu-Han Yang07561382018-02-21 13:08:37 -0800834
835 Log.i(TAG,
Yu-Han Yang74041ff2018-04-06 15:57:31 -0700836 String.format(
837 "GNSS HAL Requesting location updates from %s provider for %d millis.",
838 provider, durationMillis));
Yu-Han Yange684dda2018-05-24 10:29:39 -0700839 try {
840 locationManager.requestLocationUpdates(provider,
841 LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS, /*minDistance=*/ 0,
842 locationListener, mHandler.getLooper());
843 locationListener.numLocationUpdateRequest++;
844 mHandler.postDelayed(() -> {
845 if (--locationListener.numLocationUpdateRequest == 0) {
846 Log.i(TAG,
847 String.format("Removing location updates from %s provider.", provider));
848 locationManager.removeUpdates(locationListener);
849 }
850 }, durationMillis);
851 } catch (IllegalArgumentException e) {
852 Log.w(TAG, "Unable to request location.", e);
853 }
Yu-Han Yange7baef32018-02-09 13:58:17 -0800854 }
855
856 private void injectBestLocation(Location location) {
857 int gnssLocationFlags = LOCATION_HAS_LAT_LONG |
858 (location.hasAltitude() ? LOCATION_HAS_ALTITUDE : 0) |
859 (location.hasSpeed() ? LOCATION_HAS_SPEED : 0) |
860 (location.hasBearing() ? LOCATION_HAS_BEARING : 0) |
861 (location.hasAccuracy() ? LOCATION_HAS_HORIZONTAL_ACCURACY : 0) |
862 (location.hasVerticalAccuracy() ? LOCATION_HAS_VERTICAL_ACCURACY : 0) |
863 (location.hasSpeedAccuracy() ? LOCATION_HAS_SPEED_ACCURACY : 0) |
864 (location.hasBearingAccuracy() ? LOCATION_HAS_BEARING_ACCURACY : 0);
865
866 double latitudeDegrees = location.getLatitude();
867 double longitudeDegrees = location.getLongitude();
868 double altitudeMeters = location.getAltitude();
869 float speedMetersPerSec = location.getSpeed();
870 float bearingDegrees = location.getBearing();
871 float horizontalAccuracyMeters = location.getAccuracy();
872 float verticalAccuracyMeters = location.getVerticalAccuracyMeters();
873 float speedAccuracyMetersPerSecond = location.getSpeedAccuracyMetersPerSecond();
874 float bearingAccuracyDegrees = location.getBearingAccuracyDegrees();
875 long timestamp = location.getTime();
876 native_inject_best_location(gnssLocationFlags, latitudeDegrees, longitudeDegrees,
877 altitudeMeters, speedMetersPerSec, bearingDegrees, horizontalAccuracyMeters,
878 verticalAccuracyMeters, speedAccuracyMetersPerSecond, bearingAccuracyDegrees,
879 timestamp);
880 }
881
Yu-Han Yange7baef32018-02-09 13:58:17 -0800882 /** Returns true if the location request is too frequent. */
883 private boolean isRequestLocationRateLimited() {
884 // TODO(b/73198123): implement exponential backoff.
885 return false;
886 }
887
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400888 private void handleDownloadXtraData() {
Wyatt Riley0d6e54e22016-10-05 12:03:03 -0700889 if (!mSupportsXtra) {
890 // native code reports xtra not supported, don't try
891 Log.d(TAG, "handleDownloadXtraData() called when Xtra not supported");
892 return;
893 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800894 if (mDownloadXtraDataPending == STATE_DOWNLOADING) {
895 // already downloading data
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400896 return;
897 }
Anil Admal50ba15e2018-11-01 16:42:42 -0700898 if (!mNetworkConnectivityHandler.isDataNetworkConnected()) {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800899 // try again when network is up
900 mDownloadXtraDataPending = STATE_PENDING_NETWORK;
901 return;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400902 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800903 mDownloadXtraDataPending = STATE_DOWNLOADING;
904
Jeff Brown028872f2012-08-25 13:07:01 -0700905 // hold wake lock while task runs
Wei Wangb71c0492017-05-01 20:24:19 -0700906 mDownloadXtraWakeLock.acquire(DOWNLOAD_XTRA_DATA_TIMEOUT_MS);
Lifu Tangcbd2a142016-06-22 10:57:55 -0700907 Log.i(TAG, "WakeLock acquired by handleDownloadXtraData()");
Kevin Tang40e1baf2012-01-10 14:32:44 -0800908 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
909 @Override
910 public void run() {
Andreas Gampedfdc6ac2014-10-28 20:42:53 -0700911 GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mProperties);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800912 byte[] data = xtraDownloader.downloadXtraData();
913 if (data != null) {
destradaae21252a2015-09-08 12:32:59 -0700914 if (DEBUG) Log.d(TAG, "calling native_inject_xtra_data");
Kevin Tang40e1baf2012-01-10 14:32:44 -0800915 native_inject_xtra_data(data, data.length);
Wei Liu6f6326b2015-06-24 23:47:50 -0700916 mXtraBackOff.reset();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800917 }
918
Jeff Brown028872f2012-08-25 13:07:01 -0700919 sendMessage(DOWNLOAD_XTRA_DATA_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800920
921 if (data == null) {
922 // try again later
923 // since this is delayed and not urgent we do not hold a wake lock here
Wei Liu6f6326b2015-06-24 23:47:50 -0700924 mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA,
925 mXtraBackOff.nextBackoffMillis());
Kevin Tang40e1baf2012-01-10 14:32:44 -0800926 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800927
Wei Wangb71c0492017-05-01 20:24:19 -0700928 // Release wake lock held by task, synchronize on mLock in case multiple
929 // download tasks overrun.
930 synchronized (mLock) {
931 if (mDownloadXtraWakeLock.isHeld()) {
Zheng Zhang3cceb252017-08-07 13:51:23 -0700932 // This wakelock may have time-out, if a timeout was specified.
933 // Catch (and ignore) any timeout exceptions.
934 try {
935 mDownloadXtraWakeLock.release();
936 if (DEBUG) Log.d(TAG, "WakeLock released by handleDownloadXtraData()");
937 } catch (Exception e) {
938 Log.i(TAG, "Wakelock timeout & release race exception in "
939 + "handleDownloadXtraData()", e);
940 }
Wei Wangb71c0492017-05-01 20:24:19 -0700941 } else {
942 Log.e(TAG, "WakeLock expired before release in "
943 + "handleDownloadXtraData()");
944 }
Wei Wangc5706f62017-04-18 11:26:26 -0700945 }
Jeff Brown028872f2012-08-25 13:07:01 -0700946 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800947 });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 }
949
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400950 private void handleUpdateLocation(Location location) {
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -0400951 if (location.hasAccuracy()) {
952 native_inject_location(location.getLatitude(), location.getLongitude(),
953 location.getAccuracy());
954 }
Mike Lockwoodfd6e5f02009-05-21 11:28:20 -0400955 }
956
957 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800958 * Enables this provider. When enabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -0700959 * must be handled. Hardware may be started up
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960 * when the provider is enabled.
961 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700962 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400963 public void enable() {
Laurent Tu7b5aeca2013-01-24 15:10:24 -0800964 synchronized (mLock) {
965 if (mEnabled) return;
966 mEnabled = true;
967 }
968
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700969 sendMessage(ENABLE, 1, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400970 }
971
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700972 private void setSuplHostPort(String hostString, String portString) {
973 if (hostString != null) {
974 mSuplServerHost = hostString;
975 }
976 if (portString != null) {
977 try {
978 mSuplServerPort = Integer.parseInt(portString);
979 } catch (NumberFormatException e) {
980 Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
981 }
982 }
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700983 if (mSuplServerHost != null
984 && mSuplServerPort > TCP_MIN_PORT
985 && mSuplServerPort <= TCP_MAX_PORT) {
986 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
987 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700988 }
989
Tsuwei Chen462bcd82014-09-17 12:28:49 -0700990 /**
991 * Checks what SUPL mode to use, according to the AGPS mode as well as the
992 * allowed mode from properties.
993 *
gomo48f1a642017-11-10 20:35:46 -0800994 * @param properties GPS properties
Tsuwei Chen462bcd82014-09-17 12:28:49 -0700995 * @param agpsEnabled whether AGPS is enabled by settings value
gomo48f1a642017-11-10 20:35:46 -0800996 * @param singleShot whether "singleshot" is needed
Tsuwei Chen462bcd82014-09-17 12:28:49 -0700997 * @return SUPL mode (MSA vs MSB vs STANDALONE)
998 */
999 private int getSuplMode(Properties properties, boolean agpsEnabled, boolean singleShot) {
1000 if (agpsEnabled) {
1001 String modeString = properties.getProperty("SUPL_MODE");
1002 int suplMode = 0;
1003 if (!TextUtils.isEmpty(modeString)) {
1004 try {
1005 suplMode = Integer.parseInt(modeString);
1006 } catch (NumberFormatException e) {
1007 Log.e(TAG, "unable to parse SUPL_MODE: " + modeString);
1008 return GPS_POSITION_MODE_STANDALONE;
1009 }
1010 }
destradaabfb3bdb2015-04-29 14:42:35 -07001011 // MS-Based is the preferred mode for Assisted-GPS position computation, so we favor
1012 // such mode when it is available
1013 if (hasCapability(GPS_CAPABILITY_MSB) && (suplMode & AGPS_SUPL_MODE_MSB) != 0) {
1014 return GPS_POSITION_MODE_MS_BASED;
1015 }
1016 // for now, just as the legacy code did, we fallback to MS-Assisted if it is available,
1017 // do fallback only for single-shot requests, because it is too expensive to do for
1018 // periodic requests as well
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001019 if (singleShot
1020 && hasCapability(GPS_CAPABILITY_MSA)
1021 && (suplMode & AGPS_SUPL_MODE_MSA) != 0) {
1022 return GPS_POSITION_MODE_MS_ASSISTED;
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001023 }
1024 }
1025 return GPS_POSITION_MODE_STANDALONE;
1026 }
1027
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001028 private void handleEnable() {
1029 if (DEBUG) Log.d(TAG, "handleEnable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001030
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001031 boolean enabled = native_init();
1032
1033 if (enabled) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04001034 mSupportsXtra = native_supports_xtra();
Tsuwei Chen678c13c2014-09-22 17:48:41 -07001035
1036 // TODO: remove the following native calls if we can make sure they are redundant.
Mike Lockwood734d6032009-07-28 18:30:25 -07001037 if (mSuplServerHost != null) {
1038 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
1039 }
1040 if (mC2KServerHost != null) {
1041 native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
1042 }
destradaa13a60b02015-01-15 18:36:01 -08001043
Lifu Tang818aa2c2016-02-01 01:52:00 -08001044 mGnssMeasurementsProvider.onGpsEnabledChanged();
1045 mGnssNavigationMessageProvider.onGpsEnabledChanged();
Yu-Han Yang3557cc72018-03-21 12:48:36 -07001046 mGnssBatchingProvider.enable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001047 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001048 synchronized (mLock) {
1049 mEnabled = false;
1050 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001051 Log.w(TAG, "Failed to enable location provider");
1052 }
1053 }
1054
1055 /**
1056 * Disables this provider. When disabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -07001057 * need not be handled. Hardware may be shut
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 * down while the provider is disabled.
1059 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001060 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001061 public void disable() {
Laurent Tu7b5aeca2013-01-24 15:10:24 -08001062 synchronized (mLock) {
1063 if (!mEnabled) return;
1064 mEnabled = false;
1065 }
1066
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001067 sendMessage(ENABLE, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001068 }
1069
1070 private void handleDisable() {
Mike Lockwood89096312010-03-24 10:14:55 -04001071 if (DEBUG) Log.d(TAG, "handleDisable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072
David Christie3bc26142013-12-19 14:53:44 -08001073 updateClientUids(new WorkSource());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 stopNavigating();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001075 mAlarmManager.cancel(mWakeupIntent);
1076 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001077
Yu-Han Yang3557cc72018-03-21 12:48:36 -07001078 mGnssBatchingProvider.disable();
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001079 // do this before releasing wakelock
1080 native_cleanup();
destradaa13a60b02015-01-15 18:36:01 -08001081
Lifu Tang818aa2c2016-02-01 01:52:00 -08001082 mGnssMeasurementsProvider.onGpsEnabledChanged();
1083 mGnssNavigationMessageProvider.onGpsEnabledChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 }
1085
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001086 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001087 public boolean isEnabled() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001088 synchronized (mLock) {
1089 return mEnabled;
1090 }
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001091 }
1092
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001093 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094 public int getStatus(Bundle extras) {
Wyatt Rileyc7067412018-02-07 15:50:35 -08001095 mLocationExtras.setBundle(extras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 return mStatus;
1097 }
1098
Wyatt Rileyc7067412018-02-07 15:50:35 -08001099 private void updateStatus(int status) {
1100 if (status != mStatus) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 mStatus = status;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001102 mStatusUpdateTime = SystemClock.elapsedRealtime();
1103 }
1104 }
1105
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001106 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 public long getStatusUpdateTime() {
1108 return mStatusUpdateTime;
1109 }
1110
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001111 @Override
1112 public void setRequest(ProviderRequest request, WorkSource source) {
1113 sendMessage(SET_REQUEST, 0, new GpsRequest(request, source));
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001114 }
1115
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001116 private void handleSetRequest(ProviderRequest request, WorkSource source) {
David Christied4edf4c2014-08-12 15:22:27 -07001117 mProviderRequest = request;
1118 mWorkSource = source;
1119 updateRequirements();
1120 }
1121
1122 // Called when the requirements for GPS may have changed
1123 private void updateRequirements() {
1124 if (mProviderRequest == null || mWorkSource == null) {
1125 return;
1126 }
1127
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001128 boolean singleShot = false;
1129
1130 // see if the request is for a single update
David Christied4edf4c2014-08-12 15:22:27 -07001131 if (mProviderRequest.locationRequests != null
1132 && mProviderRequest.locationRequests.size() > 0) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001133 // if any request has zero or more than one updates
1134 // requested, then this is not single-shot mode
1135 singleShot = true;
1136
David Christied4edf4c2014-08-12 15:22:27 -07001137 for (LocationRequest lr : mProviderRequest.locationRequests) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001138 if (lr.getNumUpdates() != 1) {
1139 singleShot = false;
1140 }
1141 }
1142 }
1143
David Christied4edf4c2014-08-12 15:22:27 -07001144 if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest);
Dante Russo260d6672016-06-20 11:11:59 -07001145 if (mProviderRequest.reportLocation && !mDisableGps && isEnabled()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001146 // update client uids
David Christied4edf4c2014-08-12 15:22:27 -07001147 updateClientUids(mWorkSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148
David Christied4edf4c2014-08-12 15:22:27 -07001149 mFixInterval = (int) mProviderRequest.interval;
gomo48f1a642017-11-10 20:35:46 -08001150 mLowPowerMode = (boolean) mProviderRequest.lowPowerMode;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001151 // check for overflow
David Christied4edf4c2014-08-12 15:22:27 -07001152 if (mFixInterval != mProviderRequest.interval) {
1153 Log.w(TAG, "interval overflow: " + mProviderRequest.interval);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001154 mFixInterval = Integer.MAX_VALUE;
1155 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001156
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001157 // apply request to GPS engine
Mike Lockwood04598b62010-04-14 17:17:24 -04001158 if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
gomo48f1a642017-11-10 20:35:46 -08001159 // change period and/or lowPowerMode
Yu-Han Yangc8b9ff72018-04-17 00:47:24 -07001160 if (!setPositionMode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
gomo48f1a642017-11-10 20:35:46 -08001161 mFixInterval, 0, 0, mLowPowerMode)) {
1162 Log.e(TAG, "set_position_mode failed in updateRequirements");
Mike Lockwood04598b62010-04-14 17:17:24 -04001163 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001164 } else if (!mStarted) {
1165 // start GPS
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001166 startNavigating(singleShot);
gomo300b2402017-12-13 19:04:12 -08001167 } else {
1168 // GNSS Engine is already ON, but no GPS_CAPABILITY_SCHEDULING
1169 mAlarmManager.cancel(mTimeoutIntent);
1170 if (mFixInterval >= NO_FIX_TIMEOUT) {
1171 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
1172 // and our fix interval is not short
1173 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1174 SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent); }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001176 } else {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001177 updateClientUids(new WorkSource());
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001178
1179 stopNavigating();
1180 mAlarmManager.cancel(mWakeupIntent);
1181 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 }
1183 }
1184
Yu-Han Yangc8b9ff72018-04-17 00:47:24 -07001185 private boolean setPositionMode(int mode, int recurrence, int minInterval,
1186 int preferredAccuracy, int preferredTime, boolean lowPowerMode) {
1187 GnssPositionMode positionMode = new GnssPositionMode(mode, recurrence, minInterval,
1188 preferredAccuracy, preferredTime, lowPowerMode);
1189 if (mLastPositionMode != null && mLastPositionMode.equals(positionMode)) {
1190 return true;
1191 }
1192
1193 boolean result = native_set_position_mode(mode, recurrence, minInterval,
1194 preferredAccuracy, preferredTime, lowPowerMode);
1195 if (result) {
1196 mLastPositionMode = positionMode;
1197 } else {
1198 mLastPositionMode = null;
1199 }
1200 return result;
1201 }
1202
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001203 private void updateClientUids(WorkSource source) {
Narayan Kamath32684dd2018-01-08 17:32:51 +00001204 if (source.equals(mClientSource)) {
Victoria Leaseea78b852013-01-15 10:39:28 -08001205 return;
1206 }
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001207
Narayan Kamath32684dd2018-01-08 17:32:51 +00001208 // (1) Inform BatteryStats that the list of IDs we're tracking changed.
1209 try {
1210 mBatteryStats.noteGpsChanged(mClientSource, source);
1211 } catch (RemoteException e) {
1212 Log.w(TAG, "RemoteException", e);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001213 }
1214
Narayan Kamath32684dd2018-01-08 17:32:51 +00001215 // (2) Inform AppOps service about the list of changes to UIDs.
1216
1217 List<WorkChain>[] diffs = WorkSource.diffChains(mClientSource, source);
1218 if (diffs != null) {
1219 List<WorkChain> newChains = diffs[0];
1220 List<WorkChain> goneChains = diffs[1];
1221
1222 if (newChains != null) {
1223 for (int i = 0; i < newChains.size(); ++i) {
1224 final WorkChain newChain = newChains.get(i);
Svet Ganovf7b47252018-02-26 11:11:27 -08001225 mAppOps.startOpNoThrow(AppOpsManager.OP_GPS, newChain.getAttributionUid(),
1226 newChain.getAttributionTag());
Narayan Kamath32684dd2018-01-08 17:32:51 +00001227 }
1228 }
1229
1230 if (goneChains != null) {
1231 for (int i = 0; i < goneChains.size(); i++) {
1232 final WorkChain goneChain = goneChains.get(i);
Svet Ganovf7b47252018-02-26 11:11:27 -08001233 mAppOps.finishOp(AppOpsManager.OP_GPS, goneChain.getAttributionUid(),
1234 goneChain.getAttributionTag());
Narayan Kamath32684dd2018-01-08 17:32:51 +00001235 }
1236 }
1237
1238 mClientSource.transferWorkChains(source);
1239 }
1240
1241 // Update the flat UIDs and names list and inform app-ops of all changes.
1242 WorkSource[] changes = mClientSource.setReturningDiffs(source);
1243 if (changes != null) {
1244 WorkSource newWork = changes[0];
1245 WorkSource goneWork = changes[1];
1246
1247 // Update sources that were not previously tracked.
1248 if (newWork != null) {
1249 for (int i = 0; i < newWork.size(); i++) {
Svet Ganovf7b47252018-02-26 11:11:27 -08001250 mAppOps.startOpNoThrow(AppOpsManager.OP_GPS,
1251 newWork.get(i), newWork.getName(i));
Narayan Kamath32684dd2018-01-08 17:32:51 +00001252 }
1253 }
1254
1255 // Update sources that are no longer tracked.
1256 if (goneWork != null) {
1257 for (int i = 0; i < goneWork.size(); i++) {
Svet Ganovf7b47252018-02-26 11:11:27 -08001258 mAppOps.finishOp(AppOpsManager.OP_GPS, goneWork.get(i), goneWork.getName(i));
Dianne Hackborn2e418422009-06-22 20:00:17 -07001259 }
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001260 }
1261 }
1262 }
1263
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001264 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001265 public boolean sendExtraCommand(String command, Bundle extras) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001266
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001267 long identity = Binder.clearCallingIdentity();
Peter Visontayb25db362017-11-01 18:18:12 +00001268 try {
1269 boolean result = false;
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001270
Peter Visontayb25db362017-11-01 18:18:12 +00001271 if ("delete_aiding_data".equals(command)) {
1272 result = deleteAidingData(extras);
1273 } else if ("force_time_injection".equals(command)) {
1274 requestUtcTime();
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001275 result = true;
Peter Visontayb25db362017-11-01 18:18:12 +00001276 } else if ("force_xtra_injection".equals(command)) {
1277 if (mSupportsXtra) {
1278 xtraDownloadRequest();
1279 result = true;
1280 }
1281 } else {
1282 Log.w(TAG, "sendExtraCommand: unknown command " + command);
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001283 }
Peter Visontayb25db362017-11-01 18:18:12 +00001284 return result;
1285 } finally {
1286 Binder.restoreCallingIdentity(identity);
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001287 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001288 }
1289
1290 private boolean deleteAidingData(Bundle extras) {
1291 int flags;
1292
1293 if (extras == null) {
1294 flags = GPS_DELETE_ALL;
1295 } else {
1296 flags = 0;
1297 if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
1298 if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
1299 if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
1300 if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
1301 if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
1302 if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
1303 if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
1304 if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
1305 if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
1306 if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
1307 if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
1308 if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
1309 if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
1310 }
1311
1312 if (flags != 0) {
1313 native_delete_aiding_data(flags);
1314 return true;
1315 }
1316
1317 return false;
1318 }
1319
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001320 private void startNavigating(boolean singleShot) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001321 if (!mStarted) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001322 if (DEBUG) Log.d(TAG, "startNavigating, singleShot is " + singleShot);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001323 mTimeToFirstFix = 0;
1324 mLastFixTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001325 mStarted = true;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001326 mSingleShot = singleShot;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001327 mPositionMode = GPS_POSITION_MODE_STANDALONE;
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001328 // Notify about suppressed output, if speed limit was previously exceeded.
1329 // Elsewhere, we check again with every speed output reported.
1330 if (mItarSpeedLimitExceeded) {
1331 Log.i(TAG, "startNavigating with ITAR limit in place. Output limited " +
1332 "until slow enough speed reported.");
1333 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001334
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001335 boolean agpsEnabled =
1336 (Settings.Global.getInt(mContext.getContentResolver(),
gomo48f1a642017-11-10 20:35:46 -08001337 Settings.Global.ASSISTED_GPS_ENABLED, 1) != 0);
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001338 mPositionMode = getSuplMode(mProperties, agpsEnabled, singleShot);
Mike Lockwoodbcab8df2009-06-25 16:39:09 -04001339
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001340 if (DEBUG) {
1341 String mode;
1342
gomo48f1a642017-11-10 20:35:46 -08001343 switch (mPositionMode) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001344 case GPS_POSITION_MODE_STANDALONE:
1345 mode = "standalone";
1346 break;
1347 case GPS_POSITION_MODE_MS_ASSISTED:
1348 mode = "MS_ASSISTED";
1349 break;
1350 case GPS_POSITION_MODE_MS_BASED:
1351 mode = "MS_BASED";
1352 break;
1353 default:
1354 mode = "unknown";
1355 break;
1356 }
1357 Log.d(TAG, "setting position_mode to " + mode);
1358 }
1359
Mike Lockwood04598b62010-04-14 17:17:24 -04001360 int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
gomo48f1a642017-11-10 20:35:46 -08001361 mLowPowerMode = (boolean) mProviderRequest.lowPowerMode;
Yu-Han Yangc8b9ff72018-04-17 00:47:24 -07001362 if (!setPositionMode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
gomo48f1a642017-11-10 20:35:46 -08001363 interval, 0, 0, mLowPowerMode)) {
Mike Lockwood04598b62010-04-14 17:17:24 -04001364 mStarted = false;
1365 Log.e(TAG, "set_position_mode failed in startNavigating()");
1366 return;
1367 }
1368 if (!native_start()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 mStarted = false;
1370 Log.e(TAG, "native_start failed in startNavigating()");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001371 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 }
1373
1374 // reset SV count to zero
Wyatt Rileyc7067412018-02-07 15:50:35 -08001375 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE);
1376 mLocationExtras.reset();
Yipeng Cao282b5942017-05-17 20:31:39 -07001377 mFixRequestTime = SystemClock.elapsedRealtime();
Mike Lockwood04598b62010-04-14 17:17:24 -04001378 if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
1379 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
1380 // and our fix interval is not short
1381 if (mFixInterval >= NO_FIX_TIMEOUT) {
1382 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1383 SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
1384 }
Mike Lockwood0632ca72009-05-14 15:51:03 -04001385 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001386 }
1387 }
1388
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001389 private void stopNavigating() {
Mike Lockwood29c84342009-05-06 14:01:15 -04001390 if (DEBUG) Log.d(TAG, "stopNavigating");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001391 if (mStarted) {
1392 mStarted = false;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001393 mSingleShot = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001394 native_stop();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001395 mLastFixTime = 0;
Yu-Han Yanga50cd602018-08-28 12:33:24 -07001396 // native_stop() may reset the position mode in hardware.
1397 mLastPositionMode = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001398
1399 // reset SV count to zero
Wyatt Rileyc7067412018-02-07 15:50:35 -08001400 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE);
1401 mLocationExtras.reset();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 }
1403 }
1404
Mike Lockwood0632ca72009-05-14 15:51:03 -04001405 private void hibernate() {
1406 // stop GPS until our next fix interval arrives
1407 stopNavigating();
Mike Lockwood0632ca72009-05-14 15:51:03 -04001408 mAlarmManager.cancel(mTimeoutIntent);
1409 mAlarmManager.cancel(mWakeupIntent);
1410 long now = SystemClock.elapsedRealtime();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001411 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, mWakeupIntent);
Mike Lockwood04598b62010-04-14 17:17:24 -04001412 }
1413
1414 private boolean hasCapability(int capability) {
1415 return ((mEngineCapabilities & capability) != 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -04001416 }
1417
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419 /**
1420 * called from native code to update our position.
1421 */
Wyatt Riley5d229832017-02-10 17:06:00 -08001422 private void reportLocation(boolean hasLatLong, Location location) {
Wyatt Riley26465d22018-02-12 13:44:24 -08001423 sendMessage(REPORT_LOCATION, hasLatLong ? 1 : 0, location);
1424 }
1425
1426 private void handleReportLocation(boolean hasLatLong, Location location) {
Wyatt Riley5d229832017-02-10 17:06:00 -08001427 if (location.hasSpeed()) {
1428 mItarSpeedLimitExceeded = location.getSpeed() > ITAR_SPEED_LIMIT_METERS_PER_SECOND;
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001429 }
1430
1431 if (mItarSpeedLimitExceeded) {
1432 Log.i(TAG, "Hal reported a speed in excess of ITAR limit." +
1433 " GPS/GNSS Navigation output blocked.");
Siddharth Ray53ddc802018-03-16 12:01:52 -07001434 if (mStarted) {
1435 mGnssMetrics.logReceivedLocationStatus(false);
1436 }
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001437 return; // No output of location allowed
1438 }
1439
Wyatt Riley5d229832017-02-10 17:06:00 -08001440 if (VERBOSE) Log.v(TAG, "reportLocation " + location.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001441
Wyatt Riley26465d22018-02-12 13:44:24 -08001442 // It would be nice to push the elapsed real-time timestamp
1443 // further down the stack, but this is still useful
1444 location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
1445 location.setExtras(mLocationExtras.getBundle());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001446
Wyatt Riley26465d22018-02-12 13:44:24 -08001447 try {
1448 mILocationManager.reportLocation(location, false);
1449 } catch (RemoteException e) {
1450 Log.e(TAG, "RemoteException calling reportLocation");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451 }
1452
Siddharth Ray53ddc802018-03-16 12:01:52 -07001453 if (mStarted) {
1454 mGnssMetrics.logReceivedLocationStatus(hasLatLong);
1455 if (hasLatLong) {
1456 if (location.hasAccuracy()) {
1457 mGnssMetrics.logPositionAccuracyMeters(location.getAccuracy());
1458 }
1459 if (mTimeToFirstFix > 0) {
1460 int timeBetweenFixes = (int) (SystemClock.elapsedRealtime() - mLastFixTime);
1461 mGnssMetrics.logMissedReports(mFixInterval, timeBetweenFixes);
1462 }
Siddharth Raybb608c82017-03-16 11:33:34 -07001463 }
1464 }
1465
Yipeng Cao282b5942017-05-17 20:31:39 -07001466 mLastFixTime = SystemClock.elapsedRealtime();
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001467 // report time to first fix
Wyatt Riley5d229832017-02-10 17:06:00 -08001468 if (mTimeToFirstFix == 0 && hasLatLong) {
gomo48f1a642017-11-10 20:35:46 -08001469 mTimeToFirstFix = (int) (mLastFixTime - mFixRequestTime);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001470 if (DEBUG) Log.d(TAG, "TTFF: " + mTimeToFirstFix);
Siddharth Ray53ddc802018-03-16 12:01:52 -07001471 if (mStarted) {
1472 mGnssMetrics.logTimeToFirstFixMilliSecs(mTimeToFirstFix);
1473 }
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001474
1475 // notify status listeners
destradaaea8a8a62014-06-23 18:19:03 -07001476 mListenerHelper.onFirstFix(mTimeToFirstFix);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001477 }
1478
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001479 if (mSingleShot) {
1480 stopNavigating();
1481 }
1482
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001483 if (mStarted && mStatus != LocationProvider.AVAILABLE) {
Wyatt Rileyc7067412018-02-07 15:50:35 -08001484 // For devices that use framework scheduling, a timer may be set to ensure we don't
1485 // spend too much power searching for a location, when the requested update rate is slow.
1486 // As we just recievied a location, we'll cancel that timer.
Mike Lockwood04598b62010-04-14 17:17:24 -04001487 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001488 mAlarmManager.cancel(mTimeoutIntent);
1489 }
1490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 // send an intent to notify that the GPS is receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001492 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1493 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001494 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Wyatt Rileyc7067412018-02-07 15:50:35 -08001495 updateStatus(LocationProvider.AVAILABLE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 }
Mike Lockwood29c84342009-05-06 14:01:15 -04001497
gomo48f1a642017-11-10 20:35:46 -08001498 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted &&
1499 mFixInterval > GPS_POLLING_THRESHOLD_INTERVAL) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001500 if (DEBUG) Log.d(TAG, "got fix, hibernating");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001501 hibernate();
Mike Lockwood29c84342009-05-06 14:01:15 -04001502 }
gomo48f1a642017-11-10 20:35:46 -08001503 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504
1505 /**
1506 * called from native code to update our status
1507 */
1508 private void reportStatus(int status) {
Mike Lockwoodb8d90332010-10-18 17:59:48 -04001509 if (DEBUG) Log.v(TAG, "reportStatus status: " + status);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510
destradaaea8a8a62014-06-23 18:19:03 -07001511 boolean wasNavigating = mNavigating;
1512 switch (status) {
1513 case GPS_STATUS_SESSION_BEGIN:
1514 mNavigating = true;
1515 mEngineOn = true;
1516 break;
1517 case GPS_STATUS_SESSION_END:
1518 mNavigating = false;
1519 break;
1520 case GPS_STATUS_ENGINE_ON:
1521 mEngineOn = true;
1522 break;
1523 case GPS_STATUS_ENGINE_OFF:
1524 mEngineOn = false;
1525 mNavigating = false;
1526 break;
1527 }
Mike Lockwooddbd6fd82009-12-07 18:43:36 -05001528
destradaaea8a8a62014-06-23 18:19:03 -07001529 if (wasNavigating != mNavigating) {
destradaa13a60b02015-01-15 18:36:01 -08001530 mListenerHelper.onStatusChanged(mNavigating);
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001531
destradaaea8a8a62014-06-23 18:19:03 -07001532 // send an intent to notify that the GPS has been enabled or disabled
1533 Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
1534 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
1535 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001536 }
1537 }
1538
Wyatt Riley26465d22018-02-12 13:44:24 -08001539 // Helper class to carry data to handler for reportSvStatus
1540 private static class SvStatusInfo {
1541 public int mSvCount;
1542 public int[] mSvidWithFlags;
1543 public float[] mCn0s;
1544 public float[] mSvElevations;
1545 public float[] mSvAzimuths;
1546 public float[] mSvCarrierFreqs;
1547 }
1548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 /**
1550 * called from native code to update SV info
1551 */
Wyatt Riley26465d22018-02-12 13:44:24 -08001552 private void reportSvStatus(int svCount, int[] svidWithFlags, float[] cn0s,
1553 float[] svElevations, float[] svAzimuths, float[] svCarrierFreqs) {
1554 SvStatusInfo svStatusInfo = new SvStatusInfo();
1555 svStatusInfo.mSvCount = svCount;
1556 svStatusInfo.mSvidWithFlags = svidWithFlags;
1557 svStatusInfo.mCn0s = cn0s;
1558 svStatusInfo.mSvElevations = svElevations;
1559 svStatusInfo.mSvAzimuths = svAzimuths;
1560 svStatusInfo.mSvCarrierFreqs = svCarrierFreqs;
1561
1562 sendMessage(REPORT_SV_STATUS, 0, svStatusInfo);
1563 }
1564
1565 private void handleReportSvStatus(SvStatusInfo info) {
destradaaea8a8a62014-06-23 18:19:03 -07001566 mListenerHelper.onSvStatusChanged(
Wyatt Riley26465d22018-02-12 13:44:24 -08001567 info.mSvCount,
1568 info.mSvidWithFlags,
1569 info.mCn0s,
1570 info.mSvElevations,
1571 info.mSvAzimuths,
1572 info.mSvCarrierFreqs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001573
Siddharth Ray168f12a2017-07-10 11:55:10 -07001574 // Log CN0 as part of GNSS metrics
Wyatt Riley26465d22018-02-12 13:44:24 -08001575 mGnssMetrics.logCn0(info.mCn0s, info.mSvCount);
Siddharth Ray168f12a2017-07-10 11:55:10 -07001576
Mike Lockwood29c84342009-05-06 14:01:15 -04001577 if (VERBOSE) {
Wyatt Riley26465d22018-02-12 13:44:24 -08001578 Log.v(TAG, "SV count: " + info.mSvCount);
Lifu Tang30f95a72016-01-07 23:20:38 -08001579 }
Wyatt Rileyc9f25dd2017-05-05 13:45:23 -07001580 // Calculate number of satellites used in fix.
Lifu Tang30f95a72016-01-07 23:20:38 -08001581 int usedInFixCount = 0;
Wyatt Rileyc9f25dd2017-05-05 13:45:23 -07001582 int maxCn0 = 0;
1583 int meanCn0 = 0;
Wyatt Riley26465d22018-02-12 13:44:24 -08001584 for (int i = 0; i < info.mSvCount; i++) {
1585 if ((info.mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0) {
Lifu Tang30f95a72016-01-07 23:20:38 -08001586 ++usedInFixCount;
Wyatt Riley26465d22018-02-12 13:44:24 -08001587 if (info.mCn0s[i] > maxCn0) {
1588 maxCn0 = (int) info.mCn0s[i];
Wyatt Rileyc9f25dd2017-05-05 13:45:23 -07001589 }
Wyatt Riley26465d22018-02-12 13:44:24 -08001590 meanCn0 += info.mCn0s[i];
Lifu Tang30f95a72016-01-07 23:20:38 -08001591 }
1592 if (VERBOSE) {
Wyatt Riley26465d22018-02-12 13:44:24 -08001593 Log.v(TAG, "svid: " + (info.mSvidWithFlags[i] >> GnssStatus.SVID_SHIFT_WIDTH) +
1594 " cn0: " + info.mCn0s[i] +
1595 " elev: " + info.mSvElevations[i] +
1596 " azimuth: " + info.mSvAzimuths[i] +
1597 " carrier frequency: " + info.mSvCarrierFreqs[i] +
1598 ((info.mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) == 0
Lifu Tang30f95a72016-01-07 23:20:38 -08001599 ? " " : " E") +
Wyatt Riley26465d22018-02-12 13:44:24 -08001600 ((info.mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) == 0
Lifu Tang30f95a72016-01-07 23:20:38 -08001601 ? " " : " A") +
Wyatt Riley26465d22018-02-12 13:44:24 -08001602 ((info.mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) == 0
gomo4402af62017-01-11 13:20:13 -08001603 ? "" : "U") +
Wyatt Riley26465d22018-02-12 13:44:24 -08001604 ((info.mSvidWithFlags[i] &
1605 GnssStatus.GNSS_SV_FLAGS_HAS_CARRIER_FREQUENCY) == 0
gomo48f1a642017-11-10 20:35:46 -08001606 ? "" : "F"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001607 }
1608 }
Wyatt Rileyc9f25dd2017-05-05 13:45:23 -07001609 if (usedInFixCount > 0) {
1610 meanCn0 /= usedInFixCount;
1611 }
1612 // return number of sats used in fix instead of total reported
Wyatt Rileyc7067412018-02-07 15:50:35 -08001613 mLocationExtras.set(usedInFixCount, meanCn0, maxCn0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001615 if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
gomo48f1a642017-11-10 20:35:46 -08001616 SystemClock.elapsedRealtime() - mLastFixTime > RECENT_FIX_TIMEOUT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001617 // send an intent to notify that the GPS is no longer receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001618 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1619 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001620 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Wyatt Rileyc7067412018-02-07 15:50:35 -08001621 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 }
1623 }
Mike Lockwood58bda982009-04-14 16:25:07 -04001624
1625 /**
Mike Lockwoode3635c92009-05-11 08:38:02 -04001626 * called from native code to update AGPS status
Mike Lockwood58bda982009-04-14 16:25:07 -04001627 */
destradaa96a14702014-06-05 11:36:30 -07001628 private void reportAGpsStatus(int type, int status, byte[] ipaddr) {
Anil Admal50ba15e2018-11-01 16:42:42 -07001629 mNetworkConnectivityHandler.onReportAGpsStatus(type, status, ipaddr);
destradaae21252a2015-09-08 12:32:59 -07001630 }
1631
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001632 /**
1633 * called from native code to report NMEA data received
1634 */
Mike Lockwoodf602d362010-06-20 14:28:16 -07001635 private void reportNmea(long timestamp) {
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001636 if (!mItarSpeedLimitExceeded) {
1637 int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
1638 String nmea = new String(mNmeaBuffer, 0 /* offset */, length);
1639 mListenerHelper.onNmeaReceived(timestamp, nmea);
1640 }
destradaaea8a8a62014-06-23 18:19:03 -07001641 }
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001642
destradaaea8a8a62014-06-23 18:19:03 -07001643 /**
Wyatt Rileyaa420d52017-07-03 15:14:42 -07001644 * called from native code - GNSS measurements callback
destradaaea8a8a62014-06-23 18:19:03 -07001645 */
Lifu Tang818aa2c2016-02-01 01:52:00 -08001646 private void reportMeasurementData(GnssMeasurementsEvent event) {
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001647 if (!mItarSpeedLimitExceeded) {
Wyatt Rileyaa420d52017-07-03 15:14:42 -07001648 // send to handler to allow native to return quickly
1649 mHandler.post(new Runnable() {
1650 @Override
1651 public void run() {
1652 mGnssMeasurementsProvider.onMeasurementsAvailable(event);
1653 }
1654 });
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001655 }
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001656 }
1657
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001658 /**
Wyatt Rileyaa420d52017-07-03 15:14:42 -07001659 * called from native code - GNSS navigation message callback
destradaa4b3e3932014-07-21 18:01:47 -07001660 */
Lifu Tange8abe8e2016-04-01 10:32:05 -07001661 private void reportNavigationMessage(GnssNavigationMessage event) {
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001662 if (!mItarSpeedLimitExceeded) {
Wyatt Rileyaa420d52017-07-03 15:14:42 -07001663 // send to handler to allow native to return quickly
1664 mHandler.post(new Runnable() {
1665 @Override
1666 public void run() {
1667 mGnssNavigationMessageProvider.onNavigationMessageAvailable(event);
1668 }
1669 });
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001670 }
destradaa4b3e3932014-07-21 18:01:47 -07001671 }
1672
1673 /**
Mike Lockwood04598b62010-04-14 17:17:24 -04001674 * called from native code to inform us what the GPS engine capabilities are
1675 */
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001676 private void setEngineCapabilities(final int capabilities) {
1677 // send to handler thread for fast native return, and in-order handling
1678 mHandler.post(new Runnable() {
1679 @Override
1680 public void run() {
1681 mEngineCapabilities = capabilities;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001682
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001683 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) {
Yu-Han Yanga1862b52018-02-20 17:05:59 -08001684 mNtpTimeHelper.enablePeriodicTimeInjection();
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001685 requestUtcTime();
1686 }
destradaa6568d702014-10-27 12:47:41 -07001687
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001688 mGnssMeasurementsProvider.onCapabilitiesUpdated(hasCapability(
1689 GPS_CAPABILITY_MEASUREMENTS));
1690 mGnssNavigationMessageProvider.onCapabilitiesUpdated(hasCapability(
1691 GPS_CAPABILITY_NAV_MESSAGES));
Yu-Han Yang52057622018-04-25 00:51:22 -07001692 restartRequests();
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001693 }
1694 });
Yu-Han Yang52057622018-04-25 00:51:22 -07001695 }
1696
1697 private void restartRequests() {
1698 Log.i(TAG, "restartRequests");
1699
1700 restartLocationRequest();
1701 mGnssMeasurementsProvider.resumeIfStarted();
1702 mGnssNavigationMessageProvider.resumeIfStarted();
1703 mGnssBatchingProvider.resumeIfStarted();
1704 mGnssGeofenceProvider.resumeIfStarted();
1705 }
1706
1707 private void restartLocationRequest() {
1708 if (DEBUG) Log.d(TAG, "restartLocationRequest");
1709 mStarted = false;
1710 updateRequirements();
1711 }
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001712
1713 /**
1714 * Called from native code to inform us the hardware year.
1715 */
1716 private void setGnssYearOfHardware(final int yearOfHardware) {
1717 // mHardwareYear is simply set here, to be read elsewhere, and is volatile for safe sync
1718 if (DEBUG) Log.d(TAG, "setGnssYearOfHardware called with " + yearOfHardware);
1719 mHardwareYear = yearOfHardware;
Mike Lockwood04598b62010-04-14 17:17:24 -04001720 }
1721
1722 /**
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001723 * Called from native code to inform us the hardware model name.
Lifu Tang82f893d2016-01-21 18:15:33 -08001724 */
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001725 private void setGnssHardwareModelName(final String modelName) {
1726 // mHardwareModelName is simply set here, to be read elsewhere, and volatile for safe sync
1727 if (DEBUG) Log.d(TAG, "setGnssModelName called with " + modelName);
1728 mHardwareModelName = modelName;
Lifu Tang82f893d2016-01-21 18:15:33 -08001729 }
1730
Yu-Han Yang52057622018-04-25 00:51:22 -07001731 /**
1732 * Called from native code to inform us GNSS HAL service died.
1733 */
1734 private void reportGnssServiceDied() {
1735 if (DEBUG) Log.d(TAG, "reportGnssServiceDied");
1736 mHandler.post(() -> {
1737 class_init_native();
1738 native_init_once();
1739 if (isEnabled()) {
1740 // re-calls native_init() and other setup.
1741 handleEnable();
1742 // resend configuration into the restarted HAL service.
1743 reloadGpsProperties(mContext, mProperties);
1744 }
1745 });
1746 }
1747
Lifu Tang9363b942016-02-16 18:07:00 -08001748 public interface GnssSystemInfoProvider {
Lifu Tang82f893d2016-01-21 18:15:33 -08001749 /**
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001750 * Returns the year of underlying GPS hardware.
Lifu Tang82f893d2016-01-21 18:15:33 -08001751 */
Lifu Tang9363b942016-02-16 18:07:00 -08001752 int getGnssYearOfHardware();
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001753 /**
1754 * Returns the model name of underlying GPS hardware.
1755 */
1756 String getGnssHardwareModelName();
Lifu Tang82f893d2016-01-21 18:15:33 -08001757 }
1758
1759 /**
1760 * @hide
1761 */
Lifu Tang9363b942016-02-16 18:07:00 -08001762 public GnssSystemInfoProvider getGnssSystemInfoProvider() {
1763 return new GnssSystemInfoProvider() {
Lifu Tang82f893d2016-01-21 18:15:33 -08001764 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001765 public int getGnssYearOfHardware() {
Wyatt Rileyd87cf912017-12-05 09:31:52 -08001766 return mHardwareYear;
1767 }
1768 @Override
1769 public String getGnssHardwareModelName() {
1770 return mHardwareModelName;
Lifu Tang82f893d2016-01-21 18:15:33 -08001771 }
1772 };
1773 }
1774
Wyatt Rileycf879db2017-01-12 13:57:38 -08001775 /**
1776 * @hide
1777 */
1778 public GnssBatchingProvider getGnssBatchingProvider() {
Yu-Han Yang3557cc72018-03-21 12:48:36 -07001779 return mGnssBatchingProvider;
Wyatt Rileycf879db2017-01-12 13:57:38 -08001780 }
1781
Siddharth Raybb608c82017-03-16 11:33:34 -07001782 public interface GnssMetricsProvider {
1783 /**
1784 * Returns GNSS metrics as proto string
1785 */
1786 String getGnssMetricsAsProtoString();
1787 }
1788
1789 /**
1790 * @hide
1791 */
1792 public GnssMetricsProvider getGnssMetricsProvider() {
1793 return new GnssMetricsProvider() {
1794 @Override
1795 public String getGnssMetricsAsProtoString() {
1796 return mGnssMetrics.dumpGnssMetricsAsProtoString();
1797 }
1798 };
1799 }
1800
Wyatt Rileycf879db2017-01-12 13:57:38 -08001801 /**
Wyatt Rileycf879db2017-01-12 13:57:38 -08001802 * called from native code - GNSS location batch callback
1803 */
1804 private void reportLocationBatch(Location[] locationArray) {
1805 List<Location> locations = new ArrayList<>(Arrays.asList(locationArray));
gomo48f1a642017-11-10 20:35:46 -08001806 if (DEBUG) {
1807 Log.d(TAG, "Location batch of size " + locationArray.length + " reported");
1808 }
Wyatt Rileycf879db2017-01-12 13:57:38 -08001809 try {
1810 mILocationManager.reportLocationBatch(locations);
1811 } catch (RemoteException e) {
1812 Log.e(TAG, "RemoteException calling reportLocationBatch");
1813 }
1814 }
1815
Lifu Tang82f893d2016-01-21 18:15:33 -08001816 /**
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001817 * called from native code to request XTRA data
1818 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001819 private void xtraDownloadRequest() {
Joe Onoratof5d95cb2010-01-07 21:48:32 -05001820 if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
Mike Lockwood98e48692010-04-07 16:32:51 -04001821 sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001822 }
1823
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001824 /**
destradaa0682809a2013-08-12 18:50:30 -07001825 * Converts the GPS HAL status to the internal Geofence Hardware status.
1826 */
1827 private int getGeofenceStatus(int status) {
gomo48f1a642017-11-10 20:35:46 -08001828 switch (status) {
destradaa0682809a2013-08-12 18:50:30 -07001829 case GPS_GEOFENCE_OPERATION_SUCCESS:
1830 return GeofenceHardware.GEOFENCE_SUCCESS;
1831 case GPS_GEOFENCE_ERROR_GENERIC:
1832 return GeofenceHardware.GEOFENCE_FAILURE;
1833 case GPS_GEOFENCE_ERROR_ID_EXISTS:
1834 return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS;
1835 case GPS_GEOFENCE_ERROR_INVALID_TRANSITION:
1836 return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION;
1837 case GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES:
1838 return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES;
1839 case GPS_GEOFENCE_ERROR_ID_UNKNOWN:
1840 return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN;
1841 default:
1842 return -1;
1843 }
1844 }
1845
1846 /**
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001847 * Called from native to report GPS Geofence transition
1848 * All geofence callbacks are called on the same thread
1849 */
Wyatt Riley5d229832017-02-10 17:06:00 -08001850 private void reportGeofenceTransition(int geofenceId, Location location, int transition,
gomo48f1a642017-11-10 20:35:46 -08001851 long transitionTimestamp) {
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001852 if (mGeofenceHardwareImpl == null) {
1853 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1854 }
Wyatt Riley5d229832017-02-10 17:06:00 -08001855
destradaa0682809a2013-08-12 18:50:30 -07001856 mGeofenceHardwareImpl.reportGeofenceTransition(
1857 geofenceId,
1858 location,
1859 transition,
1860 transitionTimestamp,
1861 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1862 FusedBatchOptions.SourceTechnologies.GNSS);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001863 }
1864
1865 /**
1866 * called from native code to report GPS status change.
1867 */
Wyatt Riley5d229832017-02-10 17:06:00 -08001868 private void reportGeofenceStatus(int status, Location location) {
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001869 if (mGeofenceHardwareImpl == null) {
1870 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1871 }
destradaa0682809a2013-08-12 18:50:30 -07001872 int monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
gomo48f1a642017-11-10 20:35:46 -08001873 if (status == GPS_GEOFENCE_AVAILABLE) {
destradaa0682809a2013-08-12 18:50:30 -07001874 monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE;
1875 }
1876 mGeofenceHardwareImpl.reportGeofenceMonitorStatus(
1877 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1878 monitorStatus,
1879 location,
1880 FusedBatchOptions.SourceTechnologies.GNSS);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001881 }
1882
1883 /**
1884 * called from native code - Geofence Add callback
1885 */
1886 private void reportGeofenceAddStatus(int geofenceId, int status) {
1887 if (mGeofenceHardwareImpl == null) {
1888 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1889 }
destradaa0682809a2013-08-12 18:50:30 -07001890 mGeofenceHardwareImpl.reportGeofenceAddStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001891 }
1892
1893 /**
1894 * called from native code - Geofence Remove callback
1895 */
1896 private void reportGeofenceRemoveStatus(int geofenceId, int status) {
1897 if (mGeofenceHardwareImpl == null) {
1898 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1899 }
destradaa0682809a2013-08-12 18:50:30 -07001900 mGeofenceHardwareImpl.reportGeofenceRemoveStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001901 }
1902
1903 /**
1904 * called from native code - Geofence Pause callback
1905 */
1906 private void reportGeofencePauseStatus(int geofenceId, int status) {
1907 if (mGeofenceHardwareImpl == null) {
1908 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1909 }
destradaa0682809a2013-08-12 18:50:30 -07001910 mGeofenceHardwareImpl.reportGeofencePauseStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001911 }
1912
1913 /**
1914 * called from native code - Geofence Resume callback
1915 */
1916 private void reportGeofenceResumeStatus(int geofenceId, int status) {
1917 if (mGeofenceHardwareImpl == null) {
1918 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1919 }
destradaa0682809a2013-08-12 18:50:30 -07001920 mGeofenceHardwareImpl.reportGeofenceResumeStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001921 }
1922
Danke Xie22d1f9f2009-08-18 18:28:45 -04001923 //=============================================================
1924 // NI Client support
Miguel Torroja1e84da82010-07-27 07:02:24 +02001925 //=============================================================
Danke Xie22d1f9f2009-08-18 18:28:45 -04001926 private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
destradaaef752b62015-04-17 13:10:47 -07001927 // Sends a response for an NI request to HAL.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001928 @Override
gomo48f1a642017-11-10 20:35:46 -08001929 public boolean sendNiResponse(int notificationId, int userResponse) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001930 // TODO Add Permission check
Danke Xie22d1f9f2009-08-18 18:28:45 -04001931
gomo48f1a642017-11-10 20:35:46 -08001932 if (DEBUG) {
1933 Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
1934 ", response: " + userResponse);
1935 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02001936 native_send_ni_response(notificationId, userResponse);
1937 return true;
1938 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04001939 };
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001940
Danke Xie22d1f9f2009-08-18 18:28:45 -04001941 public INetInitiatedListener getNetInitiatedListener() {
1942 return mNetInitiatedListener;
1943 }
1944
1945 // Called by JNI function to report an NI request.
Miguel Torroja1e84da82010-07-27 07:02:24 +02001946 public void reportNiNotification(
1947 int notificationId,
1948 int niType,
1949 int notifyFlags,
1950 int timeout,
1951 int defaultResponse,
1952 String requestorId,
1953 String text,
1954 int requestorIdEncoding,
Hridya Valsaraju2ea29602016-09-13 08:38:09 -07001955 int textEncoding
gomo48f1a642017-11-10 20:35:46 -08001956 ) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001957 Log.i(TAG, "reportNiNotification: entered");
1958 Log.i(TAG, "notificationId: " + notificationId +
1959 ", niType: " + niType +
1960 ", notifyFlags: " + notifyFlags +
1961 ", timeout: " + timeout +
1962 ", defaultResponse: " + defaultResponse);
1963
1964 Log.i(TAG, "requestorId: " + requestorId +
1965 ", text: " + text +
1966 ", requestorIdEncoding: " + requestorIdEncoding +
1967 ", textEncoding: " + textEncoding);
1968
1969 GpsNiNotification notification = new GpsNiNotification();
1970
1971 notification.notificationId = notificationId;
1972 notification.niType = niType;
1973 notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
1974 notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
gomo48f1a642017-11-10 20:35:46 -08001975 notification.privacyOverride =
1976 (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
Miguel Torroja1e84da82010-07-27 07:02:24 +02001977 notification.timeout = timeout;
1978 notification.defaultResponse = defaultResponse;
1979 notification.requestorId = requestorId;
1980 notification.text = text;
1981 notification.requestorIdEncoding = requestorIdEncoding;
1982 notification.textEncoding = textEncoding;
1983
Miguel Torroja1e84da82010-07-27 07:02:24 +02001984 mNIHandler.handleNiNotification(notification);
1985 }
1986
1987 /**
1988 * Called from native code to request set id info.
1989 * We should be careful about receiving null string from the TelephonyManager,
1990 * because sending null String to JNI function would cause a crash.
1991 */
1992
1993 private void requestSetID(int flags) {
1994 TelephonyManager phone = (TelephonyManager)
1995 mContext.getSystemService(Context.TELEPHONY_SERVICE);
destradaaef752b62015-04-17 13:10:47 -07001996 int type = AGPS_SETID_TYPE_NONE;
Miguel Torroja1e84da82010-07-27 07:02:24 +02001997 String data = "";
1998
1999 if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
2000 String data_temp = phone.getSubscriberId();
2001 if (data_temp == null) {
2002 // This means the framework does not have the SIM card ready.
2003 } else {
2004 // This means the framework has the SIM card.
2005 data = data_temp;
2006 type = AGPS_SETID_TYPE_IMSI;
2007 }
gomo48f1a642017-11-10 20:35:46 -08002008 } else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002009 String data_temp = phone.getLine1Number();
2010 if (data_temp == null) {
2011 // This means the framework does not have the SIM card ready.
2012 } else {
2013 // This means the framework has the SIM card.
2014 data = data_temp;
2015 type = AGPS_SETID_TYPE_MSISDN;
2016 }
2017 }
2018 native_agps_set_id(type, data);
2019 }
2020
2021 /**
Yu-Han Yange7baef32018-02-09 13:58:17 -08002022 * Called from native code to request location info.
2023 */
2024 private void requestLocation(boolean independentFromGnss) {
2025 if (DEBUG) {
2026 Log.d(TAG, "requestLocation. independentFromGnss: " + independentFromGnss);
2027 }
2028 sendMessage(REQUEST_LOCATION, 0, independentFromGnss);
2029 }
2030
2031 /**
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04002032 * Called from native code to request utc time info
2033 */
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04002034 private void requestUtcTime() {
destradaae21252a2015-09-08 12:32:59 -07002035 if (DEBUG) Log.d(TAG, "utcTimeRequest");
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04002036 sendMessage(INJECT_NTP_TIME, 0, null);
2037 }
2038
2039 /**
Miguel Torroja1e84da82010-07-27 07:02:24 +02002040 * Called from native code to request reference location info
2041 */
Hridya Valsaraju2ea29602016-09-13 08:38:09 -07002042 private void requestRefLocation() {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002043 TelephonyManager phone = (TelephonyManager)
2044 mContext.getSystemService(Context.TELEPHONY_SERVICE);
Victoria Leased50d0c32012-10-29 13:16:17 -07002045 final int phoneType = phone.getPhoneType();
2046 if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002047 GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation();
Victoria Leased50d0c32012-10-29 13:16:17 -07002048 if ((gsm_cell != null) && (phone.getNetworkOperator() != null)
2049 && (phone.getNetworkOperator().length() > 3)) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002050 int type;
gomo48f1a642017-11-10 20:35:46 -08002051 int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0, 3));
Miguel Torroja1e84da82010-07-27 07:02:24 +02002052 int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3));
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002053 int networkType = phone.getNetworkType();
2054 if (networkType == TelephonyManager.NETWORK_TYPE_UMTS
gomo48f1a642017-11-10 20:35:46 -08002055 || networkType == TelephonyManager.NETWORK_TYPE_HSDPA
2056 || networkType == TelephonyManager.NETWORK_TYPE_HSUPA
2057 || networkType == TelephonyManager.NETWORK_TYPE_HSPA
2058 || networkType == TelephonyManager.NETWORK_TYPE_HSPAP) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002059 type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002060 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002061 type = AGPS_REF_LOCATION_TYPE_GSM_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002062 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02002063 native_agps_set_ref_location_cellid(type, mcc, mnc,
2064 gsm_cell.getLac(), gsm_cell.getCid());
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002065 } else {
gomo48f1a642017-11-10 20:35:46 -08002066 Log.e(TAG, "Error getting cell location info.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002067 }
Victoria Leased50d0c32012-10-29 13:16:17 -07002068 } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
2069 Log.e(TAG, "CDMA not supported.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002070 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02002071 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002072
Mike Lockwood98e48692010-04-07 16:32:51 -04002073 private void sendMessage(int message, int arg, Object obj) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002074 // hold a wake lock until this message is delivered
Jeff Brown028872f2012-08-25 13:07:01 -07002075 // note that this assumes the message will not be removed from the queue before
2076 // it is handled (otherwise the wake lock would be leaked).
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002077 mWakeLock.acquire();
Anil Admal4f97c942018-11-12 10:52:46 -08002078 if (DEBUG) {
2079 Log.d(TAG, "WakeLock acquired by sendMessage(" + messageIdAsString(message) + ", " + arg
Wyatt Rileycf879db2017-01-12 13:57:38 -08002080 + ", " + obj + ")");
2081 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002082 mHandler.obtainMessage(message, arg, 1, obj).sendToTarget();
Mike Lockwood98e48692010-04-07 16:32:51 -04002083 }
2084
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002085 private final class ProviderHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08002086 public ProviderHandler(Looper looper) {
2087 super(looper, null, true /*async*/);
Jeff Brown028872f2012-08-25 13:07:01 -07002088 }
2089
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002090 @Override
Mike Lockwood4a7b65e2010-10-25 16:35:55 -04002091 public void handleMessage(Message msg) {
Mike Lockwood98e48692010-04-07 16:32:51 -04002092 int message = msg.what;
2093 switch (message) {
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002094 case ENABLE:
2095 if (msg.arg1 == 1) {
2096 handleEnable();
2097 } else {
2098 handleDisable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002099 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002100 break;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002101 case SET_REQUEST:
2102 GpsRequest gpsRequest = (GpsRequest) msg.obj;
2103 handleSetRequest(gpsRequest.request, gpsRequest.source);
Mike Lockwood03ca2162010-04-01 08:10:09 -07002104 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002105 case INJECT_NTP_TIME:
Yu-Han Yanga1862b52018-02-20 17:05:59 -08002106 mNtpTimeHelper.retrieveAndInjectNtpTime();
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002107 break;
Yu-Han Yange7baef32018-02-09 13:58:17 -08002108 case REQUEST_LOCATION:
2109 handleRequestLocation((boolean) msg.obj);
2110 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002111 case DOWNLOAD_XTRA_DATA:
Wyatt Riley0d6e54e22016-10-05 12:03:03 -07002112 handleDownloadXtraData();
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002113 break;
Kevin Tang40e1baf2012-01-10 14:32:44 -08002114 case DOWNLOAD_XTRA_DATA_FINISHED:
2115 mDownloadXtraDataPending = STATE_IDLE;
2116 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002117 case UPDATE_LOCATION:
destradaae21252a2015-09-08 12:32:59 -07002118 handleUpdateLocation((Location) msg.obj);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002119 break;
destradaafb23c672015-04-16 14:01:27 -07002120 case SUBSCRIPTION_OR_SIM_CHANGED:
2121 subscriptionOrSimChanged(mContext);
2122 break;
2123 case INITIALIZE_HANDLER:
destradaae21252a2015-09-08 12:32:59 -07002124 handleInitialize();
destradaafb23c672015-04-16 14:01:27 -07002125 break;
Wyatt Riley26465d22018-02-12 13:44:24 -08002126 case REPORT_LOCATION:
2127 handleReportLocation(msg.arg1 == 1, (Location) msg.obj);
2128 break;
2129 case REPORT_SV_STATUS:
2130 handleReportSvStatus((SvStatusInfo) msg.obj);
2131 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002132 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002133 if (msg.arg2 == 1) {
2134 // wakelock was taken for this message, release it
2135 mWakeLock.release();
Anil Admal4f97c942018-11-12 10:52:46 -08002136 if (DEBUG) {
2137 Log.d(TAG, "WakeLock released by handleMessage(" + messageIdAsString(message)
Wyatt Rileycf879db2017-01-12 13:57:38 -08002138 + ", " + msg.arg1 + ", " + msg.obj + ")");
2139 }
Mike Lockwood98e48692010-04-07 16:32:51 -04002140 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002141 }
destradaafb23c672015-04-16 14:01:27 -07002142
2143 /**
Lifu Tang30f95a72016-01-07 23:20:38 -08002144 * This method is bound to {@link #GnssLocationProvider(Context, ILocationManager, Looper)}.
destradaafb23c672015-04-16 14:01:27 -07002145 * It is in charge of loading properties and registering for events that will be posted to
2146 * this handler.
2147 */
destradaae21252a2015-09-08 12:32:59 -07002148 private void handleInitialize() {
Yu-Han Yang6d317352018-03-15 11:53:01 -07002149 native_init_once();
2150
Wyatt Riley523a0cf2017-10-31 14:36:52 -07002151 /*
2152 * A cycle of native_init() and native_cleanup() is needed so that callbacks are
2153 * registered after bootup even when location is disabled.
2154 * This will allow Emergency SUPL to work even when location is disabled before device
2155 * restart.
2156 */
2157 boolean isInitialized = native_init();
gomo48f1a642017-11-10 20:35:46 -08002158 if (!isInitialized) {
Wyatt Riley523a0cf2017-10-31 14:36:52 -07002159 Log.w(TAG, "Native initialization failed at bootup");
2160 } else {
2161 native_cleanup();
2162 }
2163
destradaafb23c672015-04-16 14:01:27 -07002164 // load default GPS configuration
2165 // (this configuration might change in the future based on SIM changes)
2166 reloadGpsProperties(mContext, mProperties);
2167
2168 // TODO: When this object "finishes" we should unregister by invoking
gomo48f1a642017-11-10 20:35:46 -08002169 // SubscriptionManager.getInstance(mContext).unregister
2170 // (mOnSubscriptionsChangedListener);
destradaafb23c672015-04-16 14:01:27 -07002171 // This is not strictly necessary because it will be unregistered if the
2172 // notification fails but it is good form.
2173
2174 // Register for SubscriptionInfo list changes which is guaranteed
2175 // to invoke onSubscriptionsChanged the first time.
2176 SubscriptionManager.from(mContext)
2177 .addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
2178
2179 // listen for events
WyattRiley6593cf12018-06-23 10:37:48 -07002180 IntentFilter intentFilter = new IntentFilter();
destradaafb23c672015-04-16 14:01:27 -07002181 intentFilter.addAction(ALARM_WAKEUP);
2182 intentFilter.addAction(ALARM_TIMEOUT);
destradaafb23c672015-04-16 14:01:27 -07002183 intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
Adam Lesinski87c17df2015-05-27 13:24:13 -07002184 intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
destradaafb23c672015-04-16 14:01:27 -07002185 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
2186 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
2187 intentFilter.addAction(SIM_STATE_CHANGED);
2188 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
2189
Anil Admal50ba15e2018-11-01 16:42:42 -07002190 mNetworkConnectivityHandler.registerNetworkCallbacks();
destradaae21252a2015-09-08 12:32:59 -07002191
destradaafb23c672015-04-16 14:01:27 -07002192 // listen for PASSIVE_PROVIDER updates
2193 LocationManager locManager =
2194 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
2195 long minTime = 0;
2196 float minDistance = 0;
2197 boolean oneShot = false;
2198 LocationRequest request = LocationRequest.createFromDeprecatedProvider(
2199 LocationManager.PASSIVE_PROVIDER,
2200 minTime,
2201 minDistance,
2202 oneShot);
2203 // Don't keep track of this request since it's done on behalf of other clients
2204 // (which are kept track of separately).
2205 request.setHideFromAppOps(true);
2206 locManager.requestLocationUpdates(
2207 request,
2208 new NetworkLocationListener(),
2209 getLooper());
2210 }
2211 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002212
Yu-Han Yange7baef32018-02-09 13:58:17 -08002213 private abstract class LocationChangeListener implements LocationListener {
Yu-Han Yang07561382018-02-21 13:08:37 -08002214 int numLocationUpdateRequest;
2215
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002216 @Override
gomo48f1a642017-11-10 20:35:46 -08002217 public void onStatusChanged(String provider, int status, Bundle extras) {
2218 }
2219
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002220 @Override
gomo48f1a642017-11-10 20:35:46 -08002221 public void onProviderEnabled(String provider) {
2222 }
2223
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002224 @Override
gomo48f1a642017-11-10 20:35:46 -08002225 public void onProviderDisabled(String provider) {
2226 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002227 }
2228
Yu-Han Yange7baef32018-02-09 13:58:17 -08002229 private final class NetworkLocationListener extends LocationChangeListener {
2230 @Override
2231 public void onLocationChanged(Location location) {
2232 // this callback happens on mHandler looper
2233 if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
2234 handleUpdateLocation(location);
2235 }
2236 }
2237 }
2238
2239 private final class FusedLocationListener extends LocationChangeListener {
2240 @Override
2241 public void onLocationChanged(Location location) {
2242 if (LocationManager.FUSED_PROVIDER.equals(location.getProvider())) {
Yu-Han Yange7baef32018-02-09 13:58:17 -08002243 injectBestLocation(location);
2244 }
2245 }
2246 }
2247
Wyatt Rileycf879db2017-01-12 13:57:38 -08002248 /**
2249 * @return A string representing the given message ID.
2250 */
2251 private String messageIdAsString(int message) {
2252 switch (message) {
2253 case ENABLE:
2254 return "ENABLE";
2255 case SET_REQUEST:
2256 return "SET_REQUEST";
Wyatt Rileycf879db2017-01-12 13:57:38 -08002257 case INJECT_NTP_TIME:
2258 return "INJECT_NTP_TIME";
Yu-Han Yange7baef32018-02-09 13:58:17 -08002259 case REQUEST_LOCATION:
2260 return "REQUEST_LOCATION";
Wyatt Rileycf879db2017-01-12 13:57:38 -08002261 case DOWNLOAD_XTRA_DATA:
2262 return "DOWNLOAD_XTRA_DATA";
Wyatt Rileycf879db2017-01-12 13:57:38 -08002263 case DOWNLOAD_XTRA_DATA_FINISHED:
2264 return "DOWNLOAD_XTRA_DATA_FINISHED";
2265 case UPDATE_LOCATION:
2266 return "UPDATE_LOCATION";
2267 case SUBSCRIPTION_OR_SIM_CHANGED:
2268 return "SUBSCRIPTION_OR_SIM_CHANGED";
2269 case INITIALIZE_HANDLER:
2270 return "INITIALIZE_HANDLER";
Wyatt Riley26465d22018-02-12 13:44:24 -08002271 case REPORT_LOCATION:
2272 return "REPORT_LOCATION";
2273 case REPORT_SV_STATUS:
2274 return "REPORT_SV_STATUS";
Wyatt Rileycf879db2017-01-12 13:57:38 -08002275 default:
2276 return "<Unknown>";
2277 }
2278 }
2279
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002280 @Override
2281 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2282 StringBuilder s = new StringBuilder();
Wyatt Riley77ca4f82017-06-30 18:13:44 -07002283 s.append(" mStarted=").append(mStarted).append('\n');
destradaa25e8caf2015-08-24 14:14:44 -07002284 s.append(" mFixInterval=").append(mFixInterval).append('\n');
gomo48f1a642017-11-10 20:35:46 -08002285 s.append(" mLowPowerMode=").append(mLowPowerMode).append('\n');
Wyatt Riley74479bd2018-01-17 08:48:27 -08002286 s.append(" mGnssMeasurementsProvider.isRegistered()=")
2287 .append(mGnssMeasurementsProvider.isRegistered()).append('\n');
2288 s.append(" mGnssNavigationMessageProvider.isRegistered()=")
2289 .append(mGnssNavigationMessageProvider.isRegistered()).append('\n');
destradaa25e8caf2015-08-24 14:14:44 -07002290 s.append(" mDisableGps (battery saver mode)=").append(mDisableGps).append('\n');
2291 s.append(" mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities));
2292 s.append(" ( ");
2293 if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHEDULING ");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002294 if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
2295 if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA ");
2296 if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT ");
2297 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME ");
destradaa25e8caf2015-08-24 14:14:44 -07002298 if (hasCapability(GPS_CAPABILITY_GEOFENCING)) s.append("GEOFENCING ");
2299 if (hasCapability(GPS_CAPABILITY_MEASUREMENTS)) s.append("MEASUREMENTS ");
2300 if (hasCapability(GPS_CAPABILITY_NAV_MESSAGES)) s.append("NAV_MESSAGES ");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002301 s.append(")\n");
Siddharth Raybb608c82017-03-16 11:33:34 -07002302 s.append(mGnssMetrics.dumpGnssMetricsAsText());
2303 s.append(" native internal state: ").append(native_get_internal_state());
Wyatt Rileycf879db2017-01-12 13:57:38 -08002304 s.append("\n");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002305 pw.append(s);
2306 }
2307
Mike Lockwoodb16e7802009-08-06 09:26:02 -04002308 // preallocated to avoid memory allocation in reportNmea()
2309 private byte[] mNmeaBuffer = new byte[120];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002310
gomo48f1a642017-11-10 20:35:46 -08002311 static {
2312 class_init_native();
2313 }
2314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002315 private static native void class_init_native();
gomo48f1a642017-11-10 20:35:46 -08002316
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002317 private static native boolean native_is_supported();
gomo48f1a642017-11-10 20:35:46 -08002318
destradaaef752b62015-04-17 13:10:47 -07002319 private static native boolean native_is_gnss_configuration_supported();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002320
Yu-Han Yang6d317352018-03-15 11:53:01 -07002321 private static native void native_init_once();
2322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002323 private native boolean native_init();
gomo48f1a642017-11-10 20:35:46 -08002324
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002325 private native void native_cleanup();
gomo48f1a642017-11-10 20:35:46 -08002326
Mike Lockwood04598b62010-04-14 17:17:24 -04002327 private native boolean native_set_position_mode(int mode, int recurrence, int min_interval,
gomo48f1a642017-11-10 20:35:46 -08002328 int preferred_accuracy, int preferred_time, boolean lowPowerMode);
2329
Mike Lockwood04598b62010-04-14 17:17:24 -04002330 private native boolean native_start();
gomo48f1a642017-11-10 20:35:46 -08002331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002332 private native boolean native_stop();
gomo48f1a642017-11-10 20:35:46 -08002333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002334 private native void native_delete_aiding_data(int flags);
gomo48f1a642017-11-10 20:35:46 -08002335
Mike Lockwoodf602d362010-06-20 14:28:16 -07002336 private native int native_read_nmea(byte[] buffer, int bufferSize);
gomo48f1a642017-11-10 20:35:46 -08002337
Yu-Han Yange7baef32018-02-09 13:58:17 -08002338 private native void native_inject_best_location(
2339 int gnssLocationFlags,
2340 double latitudeDegrees,
2341 double longitudeDegrees,
2342 double altitudeMeters,
2343 float speedMetersPerSec,
2344 float bearingDegrees,
2345 float horizontalAccuracyMeters,
2346 float verticalAccuracyMeters,
2347 float speedAccuracyMetersPerSecond,
2348 float bearingAccuracyDegrees,
2349 long timestamp);
2350
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -04002351 private native void native_inject_location(double latitude, double longitude, float accuracy);
2352
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06002353 // XTRA Support
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 private native void native_inject_time(long time, long timeReference, int uncertainty);
gomo48f1a642017-11-10 20:35:46 -08002355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002356 private native boolean native_supports_xtra();
gomo48f1a642017-11-10 20:35:46 -08002357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002358 private native void native_inject_xtra_data(byte[] data, int length);
The Android Open Source Project10592532009-03-18 17:39:46 -07002359
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06002360 // DEBUG Support
2361 private native String native_get_internal_state();
2362
2363 // AGPS Support
gomo48f1a642017-11-10 20:35:46 -08002364 private native void native_agps_ni_message(byte[] msg, int length);
2365
Mike Lockwooda9e54612009-06-19 14:54:42 -04002366 private native void native_set_agps_server(int type, String hostname, int port);
Danke Xie22d1f9f2009-08-18 18:28:45 -04002367
2368 // Network-initiated (NI) Support
2369 private native void native_send_ni_response(int notificationId, int userResponse);
Miguel Torroja1e84da82010-07-27 07:02:24 +02002370
Anil Admal50ba15e2018-11-01 16:42:42 -07002371 // AGPS ril support
Miguel Torroja1e84da82010-07-27 07:02:24 +02002372 private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
2373 int lac, int cid);
gomo48f1a642017-11-10 20:35:46 -08002374
Miguel Torroja1e84da82010-07-27 07:02:24 +02002375 private native void native_agps_set_id(int type, String setid);
Mike Lockwood50130bb2010-10-11 06:22:50 -04002376
Tsuwei Chen52617bb2014-08-25 11:49:11 -07002377 // GNSS Configuration
Hridya Valsaraju2ea29602016-09-13 08:38:09 -07002378 private static native boolean native_set_supl_version(int version);
gomo48f1a642017-11-10 20:35:46 -08002379
Hridya Valsaraju2ea29602016-09-13 08:38:09 -07002380 private static native boolean native_set_supl_mode(int mode);
gomo48f1a642017-11-10 20:35:46 -08002381
Hridya Valsaraju2ea29602016-09-13 08:38:09 -07002382 private static native boolean native_set_supl_es(int es);
gomo48f1a642017-11-10 20:35:46 -08002383
Hridya Valsaraju2ea29602016-09-13 08:38:09 -07002384 private static native boolean native_set_lpp_profile(int lppProfile);
gomo48f1a642017-11-10 20:35:46 -08002385
Hridya Valsaraju2ea29602016-09-13 08:38:09 -07002386 private static native boolean native_set_gnss_pos_protocol_select(int gnssPosProtocolSelect);
gomo48f1a642017-11-10 20:35:46 -08002387
Hridya Valsaraju2ea29602016-09-13 08:38:09 -07002388 private static native boolean native_set_gps_lock(int gpsLock);
gomo48f1a642017-11-10 20:35:46 -08002389
Hridya Valsaraju2ea29602016-09-13 08:38:09 -07002390 private static native boolean native_set_emergency_supl_pdn(int emergencySuplPdn);
2391
Yu-Han Yang66c7ea92018-03-11 17:17:15 -07002392 private static native boolean native_set_satellite_blacklist(int[] constellations, int[] svIds);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002393}