blob: c272da4b420f1e1c24cafd92003d0cd0d960c6f0 [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;
20import android.app.PendingIntent;
The Android Open Source Project10592532009-03-18 17:39:46 -070021import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.content.Context;
23import android.content.Intent;
The Android Open Source Project10592532009-03-18 17:39:46 -070024import android.content.IntentFilter;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070025import android.database.Cursor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.location.Criteria;
27import android.location.IGpsStatusListener;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -040028import android.location.IGpsStatusProvider;
Mike Lockwood4e50b782009-04-03 08:24:43 -070029import android.location.ILocationManager;
Danke Xie22d1f9f2009-08-18 18:28:45 -040030import android.location.INetInitiatedListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.location.Location;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070032import android.location.LocationListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.location.LocationManager;
34import android.location.LocationProvider;
Mike Lockwood58bda982009-04-14 16:25:07 -040035import android.net.ConnectivityManager;
Mike Lockwood03d24672009-10-08 15:45:03 -040036import android.net.NetworkInfo;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070037import android.net.Uri;
Kevin Tang40e1baf2012-01-10 14:32:44 -080038import android.os.AsyncTask;
Mike Lockwood63aa5a62010-04-14 19:21:31 -040039import android.os.Binder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.os.Bundle;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040041import android.os.Handler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.os.IBinder;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040043import android.os.Message;
Mike Lockwood0528b9b2009-05-07 10:12:54 -040044import android.os.PowerManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.os.RemoteException;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -040046import android.os.ServiceManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.os.SystemClock;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070048import android.os.UserHandle;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070049import android.os.WorkSource;
Mike Lockwoodbcab8df2009-06-25 16:39:09 -040050import android.provider.Settings;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070051import android.provider.Telephony.Carriers;
Miguel Torroja1e84da82010-07-27 07:02:24 +020052import android.provider.Telephony.Sms.Intents;
Jake Hambyb49a73d2011-03-15 20:09:46 -070053import android.telephony.SmsMessage;
Miguel Torroja1e84da82010-07-27 07:02:24 +020054import android.telephony.TelephonyManager;
55import android.telephony.gsm.GsmCellLocation;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056import android.util.Log;
Jeff Sharkey104344e2011-07-10 14:20:41 -070057import android.util.NtpTrustedTime;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -040058import com.android.internal.app.IBatteryStats;
Danke Xie22d1f9f2009-08-18 18:28:45 -040059import com.android.internal.location.GpsNetInitiatedHandler;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070060import com.android.internal.location.ProviderProperties;
61import com.android.internal.location.ProviderRequest;
Danke Xie22d1f9f2009-08-18 18:28:45 -040062import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
Jake Hambyb49a73d2011-03-15 20:09:46 -070063import com.android.internal.telephony.Phone;
Wink Savillea639b312012-07-10 12:37:54 -070064import com.android.internal.telephony.PhoneConstants;
The Android Open Source Project10592532009-03-18 17:39:46 -070065
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import java.io.File;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070067import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068import java.io.FileInputStream;
69import java.io.IOException;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070070import java.io.PrintWriter;
Jeff Sharkey104344e2011-07-10 14:20:41 -070071import java.io.StringReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import java.util.ArrayList;
Mike Lockwoodf1218be2010-01-29 09:20:06 -050073import java.util.Date;
Danke Xie22d1f9f2009-08-18 18:28:45 -040074import java.util.Map.Entry;
Jake Hambyb49a73d2011-03-15 20:09:46 -070075import java.util.Properties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076
77/**
78 * A GPS implementation of LocationProvider used by LocationManager.
79 *
80 * {@hide}
81 */
Mike Lockwood89096312010-03-24 10:14:55 -040082public class GpsLocationProvider implements LocationProviderInterface {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083
84 private static final String TAG = "GpsLocationProvider";
Mike Lockwood29c84342009-05-06 14:01:15 -040085
Brian Muramatsu1715cb32012-08-08 17:32:21 -070086 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
87 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
Mike Lockwood62a8fc12010-03-22 14:23:26 -040088
Nick Pelly6fa9ad42012-07-16 12:18:23 -070089 private static final ProviderProperties PROPERTIES = new ProviderProperties(
90 true, true, false, false, true, true, true,
91 Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
92
The Android Open Source Project10592532009-03-18 17:39:46 -070093 // these need to match GpsPositionMode enum in gps.h
94 private static final int GPS_POSITION_MODE_STANDALONE = 0;
95 private static final int GPS_POSITION_MODE_MS_BASED = 1;
96 private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
97
Mike Lockwood04598b62010-04-14 17:17:24 -040098 // these need to match GpsPositionRecurrence enum in gps.h
99 private static final int GPS_POSITION_RECURRENCE_PERIODIC = 0;
100 private static final int GPS_POSITION_RECURRENCE_SINGLE = 1;
101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 // these need to match GpsStatusValue defines in gps.h
103 private static final int GPS_STATUS_NONE = 0;
104 private static final int GPS_STATUS_SESSION_BEGIN = 1;
105 private static final int GPS_STATUS_SESSION_END = 2;
106 private static final int GPS_STATUS_ENGINE_ON = 3;
107 private static final int GPS_STATUS_ENGINE_OFF = 4;
108
Mike Lockwoode3635c92009-05-11 08:38:02 -0400109 // these need to match GpsApgsStatusValue defines in gps.h
110 /** AGPS status event values. */
111 private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
112 private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
113 private static final int GPS_AGPS_DATA_CONNECTED = 3;
114 private static final int GPS_AGPS_DATA_CONN_DONE = 4;
115 private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
Mike Lockwood58bda982009-04-14 16:25:07 -0400116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 // these need to match GpsLocationFlags enum in gps.h
118 private static final int LOCATION_INVALID = 0;
119 private static final int LOCATION_HAS_LAT_LONG = 1;
120 private static final int LOCATION_HAS_ALTITUDE = 2;
121 private static final int LOCATION_HAS_SPEED = 4;
122 private static final int LOCATION_HAS_BEARING = 8;
123 private static final int LOCATION_HAS_ACCURACY = 16;
Mike Lockwoode3635c92009-05-11 08:38:02 -0400124
125// IMPORTANT - the GPS_DELETE_* symbols here must match constants in gps.h
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126 private static final int GPS_DELETE_EPHEMERIS = 0x0001;
127 private static final int GPS_DELETE_ALMANAC = 0x0002;
128 private static final int GPS_DELETE_POSITION = 0x0004;
129 private static final int GPS_DELETE_TIME = 0x0008;
130 private static final int GPS_DELETE_IONO = 0x0010;
131 private static final int GPS_DELETE_UTC = 0x0020;
132 private static final int GPS_DELETE_HEALTH = 0x0040;
133 private static final int GPS_DELETE_SVDIR = 0x0080;
134 private static final int GPS_DELETE_SVSTEER = 0x0100;
135 private static final int GPS_DELETE_SADATA = 0x0200;
136 private static final int GPS_DELETE_RTI = 0x0400;
137 private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
138 private static final int GPS_DELETE_ALL = 0xFFFF;
139
Mike Lockwood04598b62010-04-14 17:17:24 -0400140 // The GPS_CAPABILITY_* flags must match the values in gps.h
141 private static final int GPS_CAPABILITY_SCHEDULING = 0x0000001;
142 private static final int GPS_CAPABILITY_MSB = 0x0000002;
143 private static final int GPS_CAPABILITY_MSA = 0x0000004;
144 private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400145 private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010;
Mike Lockwood04598b62010-04-14 17:17:24 -0400146
Mike Lockwoode3635c92009-05-11 08:38:02 -0400147 // these need to match AGpsType enum in gps.h
148 private static final int AGPS_TYPE_SUPL = 1;
149 private static final int AGPS_TYPE_C2K = 2;
150
151 // for mAGpsDataConnectionState
152 private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
153 private static final int AGPS_DATA_CONNECTION_OPENING = 1;
154 private static final int AGPS_DATA_CONNECTION_OPEN = 2;
Mike Lockwood58bda982009-04-14 16:25:07 -0400155
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400156 // Handler messages
157 private static final int CHECK_LOCATION = 1;
158 private static final int ENABLE = 2;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700159 private static final int SET_REQUEST = 3;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400160 private static final int UPDATE_NETWORK_STATE = 4;
161 private static final int INJECT_NTP_TIME = 5;
162 private static final int DOWNLOAD_XTRA_DATA = 6;
163 private static final int UPDATE_LOCATION = 7;
164 private static final int ADD_LISTENER = 8;
165 private static final int REMOVE_LISTENER = 9;
Kevin Tang40e1baf2012-01-10 14:32:44 -0800166 private static final int INJECT_NTP_TIME_FINISHED = 10;
167 private static final int DOWNLOAD_XTRA_DATA_FINISHED = 11;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400168
Miguel Torroja1e84da82010-07-27 07:02:24 +0200169 // Request setid
170 private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
171 private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2;
172
173 // Request ref location
174 private static final int AGPS_RIL_REQUEST_REFLOC_CELLID = 1;
175 private static final int AGPS_RIL_REQUEST_REFLOC_MAC = 2;
176
177 // ref. location info
178 private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
179 private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
180 private static final int AGPS_REG_LOCATION_TYPE_MAC = 3;
181
182 // set id info
183 private static final int AGPS_SETID_TYPE_NONE = 0;
184 private static final int AGPS_SETID_TYPE_IMSI = 1;
185 private static final int AGPS_SETID_TYPE_MSISDN = 2;
186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 private static final String PROPERTIES_FILE = "/etc/gps.conf";
188
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700189 /** simpler wrapper for ProviderRequest + Worksource */
190 private static class GpsRequest {
191 public ProviderRequest request;
192 public WorkSource source;
193 public GpsRequest(ProviderRequest request, WorkSource source) {
194 this.request = request;
195 this.source = source;
196 }
197 }
198
199 private Object mLock = new Object();
200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 private int mLocationFlags = LOCATION_INVALID;
202
203 // current status
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400204 private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205
206 // time for last status update
207 private long mStatusUpdateTime = SystemClock.elapsedRealtime();
Mike Lockwoodd53ba012010-04-15 20:41:26 -0400208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 // turn off GPS fix icon if we haven't received a fix in 10 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400210 private static final long RECENT_FIX_TIMEOUT = 10 * 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211
Mike Lockwood0632ca72009-05-14 15:51:03 -0400212 // stop trying if we do not receive a fix within 60 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400213 private static final int NO_FIX_TIMEOUT = 60 * 1000;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400214
Nick Pellyb041f232012-05-07 17:12:25 -0700215 // if the fix interval is below this we leave GPS on,
216 // if above then we cycle the GPS driver.
217 // Typical hot TTTF is ~5 seconds, so 10 seconds seems sane.
218 private static final int GPS_POLLING_THRESHOLD_INTERVAL = 10 * 1000;
219
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700220 // how often to request NTP time, in milliseconds
221 // current setting 24 hours
222 private static final long NTP_INTERVAL = 24*60*60*1000;
223 // how long to wait if we have a network error in NTP or XTRA downloading
224 // current setting - 5 minutes
225 private static final long RETRY_INTERVAL = 5*60*1000;
226
227 // true if we are enabled, protected by this
228 private boolean mEnabled;
229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 // true if we have network connectivity
231 private boolean mNetworkAvailable;
232
Kevin Tang40e1baf2012-01-10 14:32:44 -0800233 // states for injecting ntp and downloading xtra data
234 private static final int STATE_PENDING_NETWORK = 0;
235 private static final int STATE_DOWNLOADING = 1;
236 private static final int STATE_IDLE = 2;
237
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400238 // flags to trigger NTP or XTRA data download when network becomes available
239 // initialized to true so we do NTP and XTRA when the network comes up after booting
Kevin Tang40e1baf2012-01-10 14:32:44 -0800240 private int mInjectNtpTimePending = STATE_PENDING_NETWORK;
241 private int mDownloadXtraDataPending = STATE_PENDING_NETWORK;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400242
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400243 // set to true if the GPS engine does not do on-demand NTP time requests
244 private boolean mPeriodicTimeInjection;
245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 // true if GPS is navigating
247 private boolean mNavigating;
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -0500248
249 // true if GPS engine is on
250 private boolean mEngineOn;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700251
Mike Lockwood04598b62010-04-14 17:17:24 -0400252 // requested frequency of fixes, in milliseconds
253 private int mFixInterval = 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254
255 // true if we started navigation
256 private boolean mStarted;
257
Mike Lockwood04598b62010-04-14 17:17:24 -0400258 // capabilities of the GPS engine
259 private int mEngineCapabilities;
260
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -0400261 // true if XTRA is supported
262 private boolean mSupportsXtra;
263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 // for calculating time to first fix
265 private long mFixRequestTime = 0;
266 // time to first fix for most recent session
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700267 private int mTimeToFirstFix = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 // time we received our last fix
269 private long mLastFixTime;
270
Mike Lockwood04598b62010-04-14 17:17:24 -0400271 private int mPositionMode;
272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273 // properties loaded from PROPERTIES_FILE
274 private Properties mProperties;
Mike Lockwood734d6032009-07-28 18:30:25 -0700275 private String mSuplServerHost;
276 private int mSuplServerPort;
277 private String mC2KServerHost;
278 private int mC2KServerPort;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400280 private final Context mContext;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700281 private final NtpTrustedTime mNtpTime;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700282 private final ILocationManager mILocationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283 private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
284 private Bundle mLocationExtras = new Bundle();
285 private ArrayList<Listener> mListeners = new ArrayList<Listener>();
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400286
Victoria Lease5c24fd02012-10-01 11:00:50 -0700287 // Handler for processing events
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400288 private Handler mHandler;
The Android Open Source Project10592532009-03-18 17:39:46 -0700289
Mike Lockwoode3635c92009-05-11 08:38:02 -0400290 private String mAGpsApn;
291 private int mAGpsDataConnectionState;
Stephen Li8efd74d2011-03-01 20:56:00 -0800292 private int mAGpsDataConnectionIpAddr;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400293 private final ConnectivityManager mConnMgr;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700294 private final GpsNetInitiatedHandler mNIHandler;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400295
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400296 // Wakelocks
297 private final static String WAKELOCK_KEY = "GpsLocationProvider";
298 private final PowerManager.WakeLock mWakeLock;
299
Mike Lockwood29c84342009-05-06 14:01:15 -0400300 // Alarms
301 private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
Mike Lockwood0632ca72009-05-14 15:51:03 -0400302 private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
Mike Lockwood29c84342009-05-06 14:01:15 -0400303 private final AlarmManager mAlarmManager;
304 private final PendingIntent mWakeupIntent;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400305 private final PendingIntent mTimeoutIntent;
Mike Lockwood29c84342009-05-06 14:01:15 -0400306
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400307 private final IBatteryStats mBatteryStats;
The Android Open Source Project10592532009-03-18 17:39:46 -0700308
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700309 // only modified on handler thread
310 private int[] mClientUids = new int[0];
Mike Lockwoodf1218be2010-01-29 09:20:06 -0500311
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400312 private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700313 @Override
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400314 public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
315 if (listener == null) {
316 throw new NullPointerException("listener is null in addGpsStatusListener");
317 }
318
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700319 synchronized (mListeners) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400320 IBinder binder = listener.asBinder();
321 int size = mListeners.size();
322 for (int i = 0; i < size; i++) {
323 Listener test = mListeners.get(i);
324 if (binder.equals(test.mListener.asBinder())) {
325 // listener already added
326 return;
327 }
328 }
329
330 Listener l = new Listener(listener);
331 binder.linkToDeath(l, 0);
332 mListeners.add(l);
333 }
334 }
335
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700336 @Override
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400337 public void removeGpsStatusListener(IGpsStatusListener listener) {
338 if (listener == null) {
339 throw new NullPointerException("listener is null in addGpsStatusListener");
340 }
341
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700342 synchronized (mListeners) {
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400343 IBinder binder = listener.asBinder();
344 Listener l = null;
345 int size = mListeners.size();
346 for (int i = 0; i < size && l == null; i++) {
347 Listener test = mListeners.get(i);
348 if (binder.equals(test.mListener.asBinder())) {
349 l = test;
350 }
351 }
352
353 if (l != null) {
354 mListeners.remove(l);
355 binder.unlinkToDeath(l, 0);
356 }
357 }
358 }
359 };
360
361 public IGpsStatusProvider getGpsStatusProvider() {
362 return mGpsStatusProvider;
363 }
364
Mike Lockwood29c84342009-05-06 14:01:15 -0400365 private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
The Android Open Source Project10592532009-03-18 17:39:46 -0700366 @Override public void onReceive(Context context, Intent intent) {
367 String action = intent.getAction();
368
Mike Lockwood29c84342009-05-06 14:01:15 -0400369 if (action.equals(ALARM_WAKEUP)) {
370 if (DEBUG) Log.d(TAG, "ALARM_WAKEUP");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700371 startNavigating();
Mike Lockwood0632ca72009-05-14 15:51:03 -0400372 } else if (action.equals(ALARM_TIMEOUT)) {
373 if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");
374 hibernate();
Miguel Torroja1e84da82010-07-27 07:02:24 +0200375 } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {
376 checkSmsSuplInit(intent);
377 } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
378 checkWapSuplInit(intent);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700379 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
380 int networkState;
381 if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false)) {
382 networkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
383 } else {
384 networkState = LocationProvider.AVAILABLE;
385 }
386
387 // retrieve NetworkInfo result for this UID
388 NetworkInfo info =
389 intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
390 ConnectivityManager connManager = (ConnectivityManager)
391 mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
392 info = connManager.getNetworkInfo(info.getType());
393
394 updateNetworkState(networkState, info);
Miguel Torroja1e84da82010-07-27 07:02:24 +0200395 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700396 }
Mike Lockwood29c84342009-05-06 14:01:15 -0400397 };
The Android Open Source Project10592532009-03-18 17:39:46 -0700398
Miguel Torroja1e84da82010-07-27 07:02:24 +0200399 private void checkSmsSuplInit(Intent intent) {
400 SmsMessage[] messages = Intents.getMessagesFromIntent(intent);
401 for (int i=0; i <messages.length; i++) {
402 byte[] supl_init = messages[i].getUserData();
403 native_agps_ni_message(supl_init,supl_init.length);
404 }
405 }
406
407 private void checkWapSuplInit(Intent intent) {
408 byte[] supl_init = (byte[]) intent.getExtra("data");
409 native_agps_ni_message(supl_init,supl_init.length);
410 }
411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800412 public static boolean isSupported() {
413 return native_is_supported();
414 }
415
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700416 public GpsLocationProvider(Context context, ILocationManager ilocationManager) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 mContext = context;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700418 mNtpTime = NtpTrustedTime.getInstance(context);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700419 mILocationManager = ilocationManager;
Mike Lockwood79e642e2010-03-17 23:19:25 -0400420 mNIHandler = new GpsNetInitiatedHandler(context);
Mike Lockwood63598a02010-02-24 11:52:59 -0500421
422 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400424 // Create a wake lock
425 PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
426 mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700427 mWakeLock.setReferenceCounted(true);
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400428
Mike Lockwood29c84342009-05-06 14:01:15 -0400429 mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
430 mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400431 mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
Mike Lockwood29c84342009-05-06 14:01:15 -0400432
Mike Lockwood58bda982009-04-14 16:25:07 -0400433 mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
434
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400435 // Battery statistics service to be notified when GPS turns on or off
436 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
437
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 mProperties = new Properties();
439 try {
440 File file = new File(PROPERTIES_FILE);
441 FileInputStream stream = new FileInputStream(file);
442 mProperties.load(stream);
443 stream.close();
Mike Lockwoode3635c92009-05-11 08:38:02 -0400444
Mike Lockwood734d6032009-07-28 18:30:25 -0700445 mSuplServerHost = mProperties.getProperty("SUPL_HOST");
Mike Lockwoode3635c92009-05-11 08:38:02 -0400446 String portString = mProperties.getProperty("SUPL_PORT");
Mike Lockwood734d6032009-07-28 18:30:25 -0700447 if (mSuplServerHost != null && portString != null) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700448 try {
Mike Lockwood734d6032009-07-28 18:30:25 -0700449 mSuplServerPort = Integer.parseInt(portString);
The Android Open Source Project10592532009-03-18 17:39:46 -0700450 } catch (NumberFormatException e) {
Mike Lockwoode3635c92009-05-11 08:38:02 -0400451 Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
452 }
453 }
454
Mike Lockwood734d6032009-07-28 18:30:25 -0700455 mC2KServerHost = mProperties.getProperty("C2K_HOST");
Mike Lockwoode3635c92009-05-11 08:38:02 -0400456 portString = mProperties.getProperty("C2K_PORT");
Mike Lockwood734d6032009-07-28 18:30:25 -0700457 if (mC2KServerHost != null && portString != null) {
Mike Lockwoode3635c92009-05-11 08:38:02 -0400458 try {
Mike Lockwood734d6032009-07-28 18:30:25 -0700459 mC2KServerPort = Integer.parseInt(portString);
Mike Lockwoode3635c92009-05-11 08:38:02 -0400460 } catch (NumberFormatException e) {
461 Log.e(TAG, "unable to parse C2K_PORT: " + portString);
The Android Open Source Project10592532009-03-18 17:39:46 -0700462 }
463 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 } catch (IOException e) {
465 Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
466 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400467
Victoria Lease5c24fd02012-10-01 11:00:50 -0700468 // construct handler, listen for events
469 mHandler = new ProviderHandler();
470 listenForBroadcasts();
471
472 // also listen for PASSIVE_PROVIDER updates
473 mHandler.post(new Runnable() {
474 @Override
475 public void run() {
476 LocationManager locManager =
477 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
478 locManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER,
479 0, 0, new NetworkLocationListener(), mHandler.getLooper());
Mike Lockwood89096312010-03-24 10:14:55 -0400480 }
Victoria Lease5c24fd02012-10-01 11:00:50 -0700481 });
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400482 }
483
Victoria Lease5c24fd02012-10-01 11:00:50 -0700484 private void listenForBroadcasts() {
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400485 IntentFilter intentFilter = new IntentFilter();
Victoria Lease5c24fd02012-10-01 11:00:50 -0700486 intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
487 intentFilter.addDataScheme("sms");
488 intentFilter.addDataAuthority("localhost","7275");
489 mContext.registerReceiver(mBroadcastReciever, intentFilter, null, mHandler);
490
491 intentFilter = new IntentFilter();
492 intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
493 try {
494 intentFilter.addDataType("application/vnd.omaloc-supl-init");
495 } catch (IntentFilter.MalformedMimeTypeException e) {
496 Log.w(TAG, "Malformed SUPL init mime type");
497 }
498 mContext.registerReceiver(mBroadcastReciever, intentFilter, null, mHandler);
499
500 intentFilter = new IntentFilter();
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400501 intentFilter.addAction(ALARM_WAKEUP);
502 intentFilter.addAction(ALARM_TIMEOUT);
Brian Muramatsub94b41f2012-08-21 16:30:57 -0700503 intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
Victoria Lease5c24fd02012-10-01 11:00:50 -0700504 mContext.registerReceiver(mBroadcastReciever, intentFilter, null, mHandler);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800505 }
506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 /**
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500508 * Returns the name of this provider.
509 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700510 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500511 public String getName() {
512 return LocationManager.GPS_PROVIDER;
513 }
514
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700515 @Override
516 public ProviderProperties getProperties() {
517 return PROPERTIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518 }
519
Mike Lockwood03d24672009-10-08 15:45:03 -0400520 public void updateNetworkState(int state, NetworkInfo info) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400521 sendMessage(UPDATE_NETWORK_STATE, state, info);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400522 }
523
524 private void handleUpdateNetworkState(int state, NetworkInfo info) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 mNetworkAvailable = (state == LocationProvider.AVAILABLE);
526
Joe Onoratof5d95cb2010-01-07 21:48:32 -0500527 if (DEBUG) {
Mike Lockwood03d24672009-10-08 15:45:03 -0400528 Log.d(TAG, "updateNetworkState " + (mNetworkAvailable ? "available" : "unavailable")
529 + " info: " + info);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800530 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400531
Mike Lockwood50130bb2010-10-11 06:22:50 -0400532 if (info != null) {
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700533 boolean dataEnabled = Settings.Global.getInt(mContext.getContentResolver(),
534 Settings.Global.MOBILE_DATA, 1) == 1;
Kevin Tanga5fe6b22011-06-05 14:25:16 -0700535 boolean networkAvailable = info.isAvailable() && dataEnabled;
536 String defaultApn = getSelectedApn();
537 if (defaultApn == null) {
538 defaultApn = "dummy-apn";
539 }
540
Mike Lockwood50130bb2010-10-11 06:22:50 -0400541 native_update_network_state(info.isConnected(), info.getType(),
Kevin Tanga5fe6b22011-06-05 14:25:16 -0700542 info.isRoaming(), networkAvailable,
543 info.getExtraInfo(), defaultApn);
Mike Lockwood50130bb2010-10-11 06:22:50 -0400544 }
545
Mike Lockwood03d24672009-10-08 15:45:03 -0400546 if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL
547 && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
548 String apnName = info.getExtraInfo();
Stephen Li83b69712011-01-25 18:47:28 -0800549 if (mNetworkAvailable) {
550 if (apnName == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700551 /* Assign a dummy value in the case of C2K as otherwise we will have a runtime
Stephen Li83b69712011-01-25 18:47:28 -0800552 exception in the following call to native_agps_data_conn_open*/
553 apnName = "dummy-apn";
554 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400555 mAGpsApn = apnName;
Stephen Li8efd74d2011-03-01 20:56:00 -0800556 if (DEBUG) Log.d(TAG, "mAGpsDataConnectionIpAddr " + mAGpsDataConnectionIpAddr);
557 if (mAGpsDataConnectionIpAddr != 0xffffffff) {
558 boolean route_result;
559 if (DEBUG) Log.d(TAG, "call requestRouteToHost");
560 route_result = mConnMgr.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_SUPL,
561 mAGpsDataConnectionIpAddr);
562 if (route_result == false) Log.d(TAG, "call requestRouteToHost failed");
563 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400564 if (DEBUG) Log.d(TAG, "call native_agps_data_conn_open");
565 native_agps_data_conn_open(apnName);
566 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
567 } else {
568 if (DEBUG) Log.d(TAG, "call native_agps_data_conn_failed");
569 mAGpsApn = null;
570 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
571 native_agps_data_conn_failed();
572 }
573 }
574
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400575 if (mNetworkAvailable) {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800576 if (mInjectNtpTimePending == STATE_PENDING_NETWORK) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400577 sendMessage(INJECT_NTP_TIME, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400578 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800579 if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400580 sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400581 }
582 }
583 }
584
585 private void handleInjectNtpTime() {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800586 if (mInjectNtpTimePending == STATE_DOWNLOADING) {
587 // already downloading data
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400588 return;
589 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800590 if (!mNetworkAvailable) {
591 // try again when network is up
592 mInjectNtpTimePending = STATE_PENDING_NETWORK;
593 return;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700594 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800595 mInjectNtpTimePending = STATE_DOWNLOADING;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700596
Jeff Brown028872f2012-08-25 13:07:01 -0700597 // hold wake lock while task runs
598 mWakeLock.acquire();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800599 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
600 @Override
601 public void run() {
602 long delay;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400603
Kevin Tang40e1baf2012-01-10 14:32:44 -0800604 // force refresh NTP cache when outdated
605 if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
606 mNtpTime.forceRefresh();
607 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400608
Kevin Tang40e1baf2012-01-10 14:32:44 -0800609 // only update when NTP time is fresh
610 if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
611 long time = mNtpTime.getCachedNtpTime();
612 long timeReference = mNtpTime.getCachedNtpTimeReference();
613 long certainty = mNtpTime.getCacheCertainty();
614 long now = System.currentTimeMillis();
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400615
Kevin Tang40e1baf2012-01-10 14:32:44 -0800616 Log.d(TAG, "NTP server returned: "
617 + time + " (" + new Date(time)
618 + ") reference: " + timeReference
619 + " certainty: " + certainty
620 + " system time offset: " + (time - now));
621
622 native_inject_time(time, timeReference, (int) certainty);
623 delay = NTP_INTERVAL;
624 } else {
625 if (DEBUG) Log.d(TAG, "requestTime failed");
626 delay = RETRY_INTERVAL;
627 }
628
Jeff Brown028872f2012-08-25 13:07:01 -0700629 sendMessage(INJECT_NTP_TIME_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800630
631 if (mPeriodicTimeInjection) {
632 // send delayed message for next NTP injection
633 // since this is delayed and not urgent we do not hold a wake lock here
Jeff Brown028872f2012-08-25 13:07:01 -0700634 mHandler.sendEmptyMessageDelayed(INJECT_NTP_TIME, delay);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800635 }
Jeff Brown028872f2012-08-25 13:07:01 -0700636
637 // release wake lock held by task
638 mWakeLock.release();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800639 }
640 });
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400641 }
642
643 private void handleDownloadXtraData() {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800644 if (mDownloadXtraDataPending == STATE_DOWNLOADING) {
645 // already downloading data
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400646 return;
647 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800648 if (!mNetworkAvailable) {
649 // try again when network is up
650 mDownloadXtraDataPending = STATE_PENDING_NETWORK;
651 return;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400652 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800653 mDownloadXtraDataPending = STATE_DOWNLOADING;
654
Jeff Brown028872f2012-08-25 13:07:01 -0700655 // hold wake lock while task runs
656 mWakeLock.acquire();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800657 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
658 @Override
659 public void run() {
660 GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
661 byte[] data = xtraDownloader.downloadXtraData();
662 if (data != null) {
663 if (DEBUG) {
664 Log.d(TAG, "calling native_inject_xtra_data");
665 }
666 native_inject_xtra_data(data, data.length);
667 }
668
Jeff Brown028872f2012-08-25 13:07:01 -0700669 sendMessage(DOWNLOAD_XTRA_DATA_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800670
671 if (data == null) {
672 // try again later
673 // since this is delayed and not urgent we do not hold a wake lock here
Jeff Brown028872f2012-08-25 13:07:01 -0700674 mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA, RETRY_INTERVAL);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800675 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800676
Jeff Brown028872f2012-08-25 13:07:01 -0700677 // release wake lock held by task
678 mWakeLock.release();
679 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800680 });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 }
682
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400683 private void handleUpdateLocation(Location location) {
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -0400684 if (location.hasAccuracy()) {
685 native_inject_location(location.getLatitude(), location.getLongitude(),
686 location.getAccuracy());
687 }
Mike Lockwoodfd6e5f02009-05-21 11:28:20 -0400688 }
689
690 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800691 * Enables this provider. When enabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -0700692 * must be handled. Hardware may be started up
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800693 * when the provider is enabled.
694 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700695 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400696 public void enable() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700697 sendMessage(ENABLE, 1, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400698 }
699
700 private void handleEnable() {
701 if (DEBUG) Log.d(TAG, "handleEnable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700703 synchronized (mLock) {
704 if (mEnabled) return;
705 mEnabled = true;
706 }
707
708 boolean enabled = native_init();
709
710 if (enabled) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -0400711 mSupportsXtra = native_supports_xtra();
Mike Lockwood734d6032009-07-28 18:30:25 -0700712 if (mSuplServerHost != null) {
713 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
714 }
715 if (mC2KServerHost != null) {
716 native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
717 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800718 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700719 synchronized (mLock) {
720 mEnabled = false;
721 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800722 Log.w(TAG, "Failed to enable location provider");
723 }
724 }
725
726 /**
727 * Disables this provider. When disabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -0700728 * need not be handled. Hardware may be shut
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 * down while the provider is disabled.
730 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700731 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400732 public void disable() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700733 sendMessage(ENABLE, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400734 }
735
736 private void handleDisable() {
Mike Lockwood89096312010-03-24 10:14:55 -0400737 if (DEBUG) Log.d(TAG, "handleDisable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800738
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700739 synchronized (mLock) {
740 if (!mEnabled) return;
741 mEnabled = false;
742 }
743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744 stopNavigating();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700745 mAlarmManager.cancel(mWakeupIntent);
746 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -0500748 // do this before releasing wakelock
749 native_cleanup();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 }
751
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700752 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500753 public boolean isEnabled() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700754 synchronized (mLock) {
755 return mEnabled;
756 }
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500757 }
758
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700759 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 public int getStatus(Bundle extras) {
761 if (extras != null) {
762 extras.putInt("satellites", mSvCount);
763 }
764 return mStatus;
765 }
766
767 private void updateStatus(int status, int svCount) {
768 if (status != mStatus || svCount != mSvCount) {
769 mStatus = status;
770 mSvCount = svCount;
771 mLocationExtras.putInt("satellites", svCount);
772 mStatusUpdateTime = SystemClock.elapsedRealtime();
773 }
774 }
775
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700776 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 public long getStatusUpdateTime() {
778 return mStatusUpdateTime;
779 }
780
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700781 @Override
782 public void setRequest(ProviderRequest request, WorkSource source) {
783 sendMessage(SET_REQUEST, 0, new GpsRequest(request, source));
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400784 }
785
Victoria Leaseb711d572012-10-02 13:14:11 -0700786 @Override
787 public void switchUser(int userId) {
788 // nothing to do here
789 }
790
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700791 private void handleSetRequest(ProviderRequest request, WorkSource source) {
792 if (DEBUG) Log.d(TAG, "setRequest " + request);
793
794
795
796 if (request.reportLocation) {
797 // update client uids
798 int[] uids = new int[source.size()];
799 for (int i=0; i < source.size(); i++) {
800 uids[i] = source.get(i);
Mike Lockwood04598b62010-04-14 17:17:24 -0400801 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700802 updateClientUids(uids);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800803
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700804 mFixInterval = (int) request.interval;
Mike Lockwood03ca2162010-04-01 08:10:09 -0700805
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700806 // check for overflow
807 if (mFixInterval != request.interval) {
808 Log.w(TAG, "interval overflow: " + request.interval);
809 mFixInterval = Integer.MAX_VALUE;
810 }
Mike Lockwood03ca2162010-04-01 08:10:09 -0700811
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700812 // apply request to GPS engine
Mike Lockwood04598b62010-04-14 17:17:24 -0400813 if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700814 // change period
Mike Lockwood04598b62010-04-14 17:17:24 -0400815 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
816 mFixInterval, 0, 0)) {
817 Log.e(TAG, "set_position_mode failed in setMinTime()");
818 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700819 } else if (!mStarted) {
820 // start GPS
821 startNavigating();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700823 } else {
824 updateClientUids(new int[0]);
825
826 stopNavigating();
827 mAlarmManager.cancel(mWakeupIntent);
828 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 }
830 }
831
832 private final class Listener implements IBinder.DeathRecipient {
833 final IGpsStatusListener mListener;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800835 Listener(IGpsStatusListener listener) {
836 mListener = listener;
837 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700838
839 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 public void binderDied() {
Joe Onoratof5d95cb2010-01-07 21:48:32 -0500841 if (DEBUG) Log.d(TAG, "GPS status listener died");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800842
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700843 synchronized (mListeners) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844 mListeners.remove(this);
845 }
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -0700846 if (mListener != null) {
847 mListener.asBinder().unlinkToDeath(this, 0);
848 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800849 }
850 }
851
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700852 private void updateClientUids(int[] uids) {
853 // Find uid's that were not previously tracked
854 for (int uid1 : uids) {
855 boolean newUid = true;
856 for (int uid2 : mClientUids) {
857 if (uid1 == uid2) {
858 newUid = false;
859 break;
860 }
Dianne Hackborn2e418422009-06-22 20:00:17 -0700861 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700862 if (newUid) {
Dianne Hackborn2e418422009-06-22 20:00:17 -0700863 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700864 mBatteryStats.noteStartGps(uid1);
Dianne Hackborn2e418422009-06-22 20:00:17 -0700865 } catch (RemoteException e) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700866 Log.w(TAG, "RemoteException", e);
867 }
868 }
869 }
870
871 // Find uid'd that were tracked but have now disappeared
872 for (int uid1 : mClientUids) {
873 boolean oldUid = true;
874 for (int uid2 : uids) {
875 if (uid1 == uid2) {
876 oldUid = false;
877 break;
878 }
879 }
880 if (oldUid) {
881 try {
882 mBatteryStats.noteStopGps(uid1);
883 } catch (RemoteException e) {
884 Log.w(TAG, "RemoteException", e);
Dianne Hackborn2e418422009-06-22 20:00:17 -0700885 }
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400886 }
887 }
Nick Pellyf2033e42012-08-17 11:55:10 -0700888
889 // save current uids
890 mClientUids = uids;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400891 }
892
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700893 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800894 public boolean sendExtraCommand(String command, Bundle extras) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700895
Mike Lockwood63aa5a62010-04-14 19:21:31 -0400896 long identity = Binder.clearCallingIdentity();
897 boolean result = false;
898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800899 if ("delete_aiding_data".equals(command)) {
Mike Lockwood63aa5a62010-04-14 19:21:31 -0400900 result = deleteAidingData(extras);
901 } else if ("force_time_injection".equals(command)) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400902 sendMessage(INJECT_NTP_TIME, 0, null);
Mike Lockwood63aa5a62010-04-14 19:21:31 -0400903 result = true;
904 } else if ("force_xtra_injection".equals(command)) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -0400905 if (mSupportsXtra) {
Mike Lockwood93bc44d2009-05-20 16:58:22 -0400906 xtraDownloadRequest();
Mike Lockwood63aa5a62010-04-14 19:21:31 -0400907 result = true;
Mike Lockwood93bc44d2009-05-20 16:58:22 -0400908 }
Mike Lockwood63aa5a62010-04-14 19:21:31 -0400909 } else {
910 Log.w(TAG, "sendExtraCommand: unknown command " + command);
Mike Lockwood93bc44d2009-05-20 16:58:22 -0400911 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700912
Mike Lockwood63aa5a62010-04-14 19:21:31 -0400913 Binder.restoreCallingIdentity(identity);
914 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800915 }
916
917 private boolean deleteAidingData(Bundle extras) {
918 int flags;
919
920 if (extras == null) {
921 flags = GPS_DELETE_ALL;
922 } else {
923 flags = 0;
924 if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
925 if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
926 if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
927 if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
928 if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
929 if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
930 if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
931 if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
932 if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
933 if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
934 if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
935 if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
936 if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
937 }
938
939 if (flags != 0) {
940 native_delete_aiding_data(flags);
941 return true;
942 }
943
944 return false;
945 }
946
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700947 private void startNavigating() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 if (!mStarted) {
Mike Lockwood29c84342009-05-06 14:01:15 -0400949 if (DEBUG) Log.d(TAG, "startNavigating");
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700950 mTimeToFirstFix = 0;
951 mLastFixTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800952 mStarted = true;
Mike Lockwood03ca2162010-04-01 08:10:09 -0700953 mPositionMode = GPS_POSITION_MODE_STANDALONE;
954
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700955 if (Settings.Global.getInt(mContext.getContentResolver(),
956 Settings.Global.ASSISTED_GPS_ENABLED, 1) != 0) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700957 if (hasCapability(GPS_CAPABILITY_MSB)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -0700958 mPositionMode = GPS_POSITION_MODE_MS_BASED;
959 }
Mike Lockwoodbcab8df2009-06-25 16:39:09 -0400960 }
961
Mike Lockwood04598b62010-04-14 17:17:24 -0400962 int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
963 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
964 interval, 0, 0)) {
965 mStarted = false;
966 Log.e(TAG, "set_position_mode failed in startNavigating()");
967 return;
968 }
969 if (!native_start()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970 mStarted = false;
971 Log.e(TAG, "native_start failed in startNavigating()");
Mike Lockwood0632ca72009-05-14 15:51:03 -0400972 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 }
974
975 // reset SV count to zero
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400976 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
Mike Lockwood29c84342009-05-06 14:01:15 -0400977 mFixRequestTime = System.currentTimeMillis();
Mike Lockwood04598b62010-04-14 17:17:24 -0400978 if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
979 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
980 // and our fix interval is not short
981 if (mFixInterval >= NO_FIX_TIMEOUT) {
982 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
983 SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
984 }
Mike Lockwood0632ca72009-05-14 15:51:03 -0400985 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986 }
987 }
988
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400989 private void stopNavigating() {
Mike Lockwood29c84342009-05-06 14:01:15 -0400990 if (DEBUG) Log.d(TAG, "stopNavigating");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800991 if (mStarted) {
992 mStarted = false;
993 native_stop();
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700994 mTimeToFirstFix = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800995 mLastFixTime = 0;
996 mLocationFlags = LOCATION_INVALID;
997
998 // reset SV count to zero
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400999 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 }
1001 }
1002
Mike Lockwood0632ca72009-05-14 15:51:03 -04001003 private void hibernate() {
1004 // stop GPS until our next fix interval arrives
1005 stopNavigating();
Mike Lockwood0632ca72009-05-14 15:51:03 -04001006 mAlarmManager.cancel(mTimeoutIntent);
1007 mAlarmManager.cancel(mWakeupIntent);
1008 long now = SystemClock.elapsedRealtime();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001009 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, mWakeupIntent);
Mike Lockwood04598b62010-04-14 17:17:24 -04001010 }
1011
1012 private boolean hasCapability(int capability) {
1013 return ((mEngineCapabilities & capability) != 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -04001014 }
1015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 /**
1017 * called from native code to update our position.
1018 */
1019 private void reportLocation(int flags, double latitude, double longitude, double altitude,
1020 float speed, float bearing, float accuracy, long timestamp) {
Mike Lockwood29c84342009-05-06 14:01:15 -04001021 if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001022 " timestamp: " + timestamp);
1023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001024 synchronized (mLocation) {
1025 mLocationFlags = flags;
1026 if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1027 mLocation.setLatitude(latitude);
1028 mLocation.setLongitude(longitude);
1029 mLocation.setTime(timestamp);
Nick Pelly2eeeec22012-07-18 13:13:37 -07001030 // It would be nice to push the elapsed real-time timestamp
1031 // further down the stack, but this is still useful
Philip Milne41180122012-09-26 11:29:25 -07001032 mLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 }
1034 if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
1035 mLocation.setAltitude(altitude);
1036 } else {
1037 mLocation.removeAltitude();
1038 }
1039 if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
1040 mLocation.setSpeed(speed);
1041 } else {
1042 mLocation.removeSpeed();
1043 }
1044 if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
1045 mLocation.setBearing(bearing);
1046 } else {
1047 mLocation.removeBearing();
1048 }
1049 if ((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
1050 mLocation.setAccuracy(accuracy);
1051 } else {
1052 mLocation.removeAccuracy();
1053 }
Sean Barbeauced2b2c2011-12-19 04:43:07 -05001054 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001056 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001057 mILocationManager.reportLocation(mLocation, false);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001058 } catch (RemoteException e) {
1059 Log.e(TAG, "RemoteException calling reportLocation");
1060 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001061 }
1062
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001063 mLastFixTime = System.currentTimeMillis();
1064 // report time to first fix
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001065 if (mTimeToFirstFix == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1066 mTimeToFirstFix = (int)(mLastFixTime - mFixRequestTime);
1067 if (DEBUG) Log.d(TAG, "TTFF: " + mTimeToFirstFix);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001068
1069 // notify status listeners
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001070 synchronized (mListeners) {
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001071 int size = mListeners.size();
1072 for (int i = 0; i < size; i++) {
1073 Listener listener = mListeners.get(i);
1074 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001075 listener.mListener.onFirstFix(mTimeToFirstFix);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001076 } catch (RemoteException e) {
1077 Log.w(TAG, "RemoteException in stopNavigating");
1078 mListeners.remove(listener);
1079 // adjust for size of list changing
1080 size--;
1081 }
1082 }
1083 }
1084 }
1085
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001086 if (mStarted && mStatus != LocationProvider.AVAILABLE) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001087 // we want to time out if we do not receive a fix
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001088 // within the time out and we are requesting infrequent fixes
Mike Lockwood04598b62010-04-14 17:17:24 -04001089 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001090 mAlarmManager.cancel(mTimeoutIntent);
1091 }
1092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 // send an intent to notify that the GPS is receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001094 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1095 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001096 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001097 updateStatus(LocationProvider.AVAILABLE, mSvCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 }
Mike Lockwood29c84342009-05-06 14:01:15 -04001099
Nick Pellyb041f232012-05-07 17:12:25 -07001100 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted &&
1101 mFixInterval > GPS_POLLING_THRESHOLD_INTERVAL) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001102 if (DEBUG) Log.d(TAG, "got fix, hibernating");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001103 hibernate();
Mike Lockwood29c84342009-05-06 14:01:15 -04001104 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 }
1106
1107 /**
1108 * called from native code to update our status
1109 */
1110 private void reportStatus(int status) {
Mike Lockwoodb8d90332010-10-18 17:59:48 -04001111 if (DEBUG) Log.v(TAG, "reportStatus status: " + status);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001113 synchronized (mListeners) {
Dianne Hackborn2e418422009-06-22 20:00:17 -07001114 boolean wasNavigating = mNavigating;
Mike Lockwooddbd6fd82009-12-07 18:43:36 -05001115
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001116 switch (status) {
1117 case GPS_STATUS_SESSION_BEGIN:
1118 mNavigating = true;
Mike Lockwood271f9f12010-02-02 11:41:52 -05001119 mEngineOn = true;
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001120 break;
1121 case GPS_STATUS_SESSION_END:
1122 mNavigating = false;
1123 break;
1124 case GPS_STATUS_ENGINE_ON:
1125 mEngineOn = true;
1126 break;
1127 case GPS_STATUS_ENGINE_OFF:
1128 mEngineOn = false;
Mike Lockwood271f9f12010-02-02 11:41:52 -05001129 mNavigating = false;
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001130 break;
1131 }
1132
Mike Lockwooddbd6fd82009-12-07 18:43:36 -05001133 if (wasNavigating != mNavigating) {
1134 int size = mListeners.size();
1135 for (int i = 0; i < size; i++) {
1136 Listener listener = mListeners.get(i);
1137 try {
1138 if (mNavigating) {
1139 listener.mListener.onGpsStarted();
1140 } else {
1141 listener.mListener.onGpsStopped();
1142 }
1143 } catch (RemoteException e) {
1144 Log.w(TAG, "RemoteException in reportStatus");
1145 mListeners.remove(listener);
1146 // adjust for size of list changing
1147 size--;
1148 }
1149 }
1150
Mike Lockwooddbd6fd82009-12-07 18:43:36 -05001151 // send an intent to notify that the GPS has been enabled or disabled.
Mike Lockwood00b74272010-03-26 10:41:48 -04001152 Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
1153 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001154 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001155 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156 }
1157 }
1158
1159 /**
1160 * called from native code to update SV info
1161 */
1162 private void reportSvStatus() {
1163
1164 int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001165
1166 synchronized (mListeners) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167 int size = mListeners.size();
1168 for (int i = 0; i < size; i++) {
1169 Listener listener = mListeners.get(i);
1170 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001171 listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs,
1172 mSvElevations, mSvAzimuths, mSvMasks[EPHEMERIS_MASK],
1173 mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 } catch (RemoteException e) {
1175 Log.w(TAG, "RemoteException in reportSvInfo");
1176 mListeners.remove(listener);
1177 // adjust for size of list changing
1178 size--;
1179 }
1180 }
1181 }
1182
Mike Lockwood29c84342009-05-06 14:01:15 -04001183 if (VERBOSE) {
1184 Log.v(TAG, "SV count: " + svCount +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001185 " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) +
1186 " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK]));
1187 for (int i = 0; i < svCount; i++) {
Mike Lockwood29c84342009-05-06 14:01:15 -04001188 Log.v(TAG, "sv: " + mSvs[i] +
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001189 " snr: " + mSnrs[i]/10 +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 " elev: " + mSvElevations[i] +
1191 " azimuth: " + mSvAzimuths[i] +
1192 ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? " " : " E") +
1193 ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? " " : " A") +
1194 ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U"));
1195 }
1196 }
1197
Kevin.KY Tsai0881f4f2010-05-21 15:10:39 -04001198 // return number of sets used in fix instead of total
1199 updateStatus(mStatus, Integer.bitCount(mSvMasks[USED_FOR_FIX_MASK]));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001200
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001201 if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
Mike Lockwood04598b62010-04-14 17:17:24 -04001202 System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 // send an intent to notify that the GPS is no longer receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001204 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1205 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001206 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001207 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001208 }
1209 }
Mike Lockwood58bda982009-04-14 16:25:07 -04001210
1211 /**
Mike Lockwoode3635c92009-05-11 08:38:02 -04001212 * called from native code to update AGPS status
Mike Lockwood58bda982009-04-14 16:25:07 -04001213 */
Stephen Li8efd74d2011-03-01 20:56:00 -08001214 private void reportAGpsStatus(int type, int status, int ipaddr) {
Mike Lockwood58bda982009-04-14 16:25:07 -04001215 switch (status) {
Mike Lockwoode3635c92009-05-11 08:38:02 -04001216 case GPS_REQUEST_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001217 if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
Mike Lockwood2acfd342010-09-22 12:13:39 -04001218 // Set mAGpsDataConnectionState before calling startUsingNetworkFeature
1219 // to avoid a race condition with handleUpdateNetworkState()
1220 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
1221 int result = mConnMgr.startUsingNetworkFeature(
Mike Lockwood58bda982009-04-14 16:25:07 -04001222 ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
Stephen Li8efd74d2011-03-01 20:56:00 -08001223 mAGpsDataConnectionIpAddr = ipaddr;
Wink Savillea639b312012-07-10 12:37:54 -07001224 if (result == PhoneConstants.APN_ALREADY_ACTIVE) {
1225 if (DEBUG) Log.d(TAG, "PhoneConstants.APN_ALREADY_ACTIVE");
Mike Lockwoodb362a9a2009-06-22 16:20:39 -04001226 if (mAGpsApn != null) {
Stephen Li8efd74d2011-03-01 20:56:00 -08001227 Log.d(TAG, "mAGpsDataConnectionIpAddr " + mAGpsDataConnectionIpAddr);
1228 if (mAGpsDataConnectionIpAddr != 0xffffffff) {
1229 boolean route_result;
1230 if (DEBUG) Log.d(TAG, "call requestRouteToHost");
1231 route_result = mConnMgr.requestRouteToHost(
1232 ConnectivityManager.TYPE_MOBILE_SUPL,
1233 mAGpsDataConnectionIpAddr);
1234 if (route_result == false) Log.d(TAG, "call requestRouteToHost failed");
1235 }
Mike Lockwoodb362a9a2009-06-22 16:20:39 -04001236 native_agps_data_conn_open(mAGpsApn);
1237 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
1238 } else {
Wink Savillea639b312012-07-10 12:37:54 -07001239 Log.e(TAG, "mAGpsApn not set when receiving PhoneConstants.APN_ALREADY_ACTIVE");
Mike Lockwood2acfd342010-09-22 12:13:39 -04001240 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
Mike Lockwoodb362a9a2009-06-22 16:20:39 -04001241 native_agps_data_conn_failed();
1242 }
Wink Savillea639b312012-07-10 12:37:54 -07001243 } else if (result == PhoneConstants.APN_REQUEST_STARTED) {
1244 if (DEBUG) Log.d(TAG, "PhoneConstants.APN_REQUEST_STARTED");
Mike Lockwood2acfd342010-09-22 12:13:39 -04001245 // Nothing to do here
Mike Lockwood58bda982009-04-14 16:25:07 -04001246 } else {
Mike Lockwoodb8d90332010-10-18 17:59:48 -04001247 if (DEBUG) Log.d(TAG, "startUsingNetworkFeature failed");
Mike Lockwood2acfd342010-09-22 12:13:39 -04001248 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001249 native_agps_data_conn_failed();
Mike Lockwood58bda982009-04-14 16:25:07 -04001250 }
1251 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001252 case GPS_RELEASE_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001253 if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
Mike Lockwoode3635c92009-05-11 08:38:02 -04001254 if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
Mike Lockwood58bda982009-04-14 16:25:07 -04001255 mConnMgr.stopUsingNetworkFeature(
1256 ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
Mike Lockwoode3635c92009-05-11 08:38:02 -04001257 native_agps_data_conn_closed();
1258 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
Mike Lockwood58bda982009-04-14 16:25:07 -04001259 }
1260 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001261 case GPS_AGPS_DATA_CONNECTED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001262 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001263 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001264 case GPS_AGPS_DATA_CONN_DONE:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001265 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
Mike Lockwood58bda982009-04-14 16:25:07 -04001266 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001267 case GPS_AGPS_DATA_CONN_FAILED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001268 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001269 break;
1270 }
1271 }
1272
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001273 /**
1274 * called from native code to report NMEA data received
1275 */
Mike Lockwoodf602d362010-06-20 14:28:16 -07001276 private void reportNmea(long timestamp) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001277 synchronized (mListeners) {
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001278 int size = mListeners.size();
1279 if (size > 0) {
1280 // don't bother creating the String if we have no listeners
Mike Lockwoodf602d362010-06-20 14:28:16 -07001281 int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001282 String nmea = new String(mNmeaBuffer, 0, length);
1283
1284 for (int i = 0; i < size; i++) {
1285 Listener listener = mListeners.get(i);
1286 try {
1287 listener.mListener.onNmeaReceived(timestamp, nmea);
1288 } catch (RemoteException e) {
1289 Log.w(TAG, "RemoteException in reportNmea");
1290 mListeners.remove(listener);
1291 // adjust for size of list changing
1292 size--;
1293 }
1294 }
1295 }
1296 }
1297 }
1298
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001299 /**
Mike Lockwood04598b62010-04-14 17:17:24 -04001300 * called from native code to inform us what the GPS engine capabilities are
1301 */
1302 private void setEngineCapabilities(int capabilities) {
1303 mEngineCapabilities = capabilities;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001304
1305 if (!hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME) && !mPeriodicTimeInjection) {
1306 mPeriodicTimeInjection = true;
1307 requestUtcTime();
1308 }
Mike Lockwood04598b62010-04-14 17:17:24 -04001309 }
1310
1311 /**
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001312 * called from native code to request XTRA data
1313 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001314 private void xtraDownloadRequest() {
Joe Onoratof5d95cb2010-01-07 21:48:32 -05001315 if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
Mike Lockwood98e48692010-04-07 16:32:51 -04001316 sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001317 }
1318
Danke Xie22d1f9f2009-08-18 18:28:45 -04001319 //=============================================================
1320 // NI Client support
Miguel Torroja1e84da82010-07-27 07:02:24 +02001321 //=============================================================
Danke Xie22d1f9f2009-08-18 18:28:45 -04001322 private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001323 // Sends a response for an NI reqeust to HAL.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001324 @Override
Miguel Torroja1e84da82010-07-27 07:02:24 +02001325 public boolean sendNiResponse(int notificationId, int userResponse)
1326 {
1327 // TODO Add Permission check
Danke Xie22d1f9f2009-08-18 18:28:45 -04001328
Miguel Torroja1e84da82010-07-27 07:02:24 +02001329 if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
1330 ", response: " + userResponse);
1331 native_send_ni_response(notificationId, userResponse);
1332 return true;
1333 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04001334 };
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001335
Danke Xie22d1f9f2009-08-18 18:28:45 -04001336 public INetInitiatedListener getNetInitiatedListener() {
1337 return mNetInitiatedListener;
1338 }
1339
1340 // Called by JNI function to report an NI request.
Miguel Torroja1e84da82010-07-27 07:02:24 +02001341 public void reportNiNotification(
1342 int notificationId,
1343 int niType,
1344 int notifyFlags,
1345 int timeout,
1346 int defaultResponse,
1347 String requestorId,
1348 String text,
1349 int requestorIdEncoding,
1350 int textEncoding,
1351 String extras // Encoded extra data
Danke Xie22d1f9f2009-08-18 18:28:45 -04001352 )
Miguel Torroja1e84da82010-07-27 07:02:24 +02001353 {
1354 Log.i(TAG, "reportNiNotification: entered");
1355 Log.i(TAG, "notificationId: " + notificationId +
1356 ", niType: " + niType +
1357 ", notifyFlags: " + notifyFlags +
1358 ", timeout: " + timeout +
1359 ", defaultResponse: " + defaultResponse);
1360
1361 Log.i(TAG, "requestorId: " + requestorId +
1362 ", text: " + text +
1363 ", requestorIdEncoding: " + requestorIdEncoding +
1364 ", textEncoding: " + textEncoding);
1365
1366 GpsNiNotification notification = new GpsNiNotification();
1367
1368 notification.notificationId = notificationId;
1369 notification.niType = niType;
1370 notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
1371 notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
1372 notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
1373 notification.timeout = timeout;
1374 notification.defaultResponse = defaultResponse;
1375 notification.requestorId = requestorId;
1376 notification.text = text;
1377 notification.requestorIdEncoding = requestorIdEncoding;
1378 notification.textEncoding = textEncoding;
1379
1380 // Process extras, assuming the format is
1381 // one of more lines of "key = value"
1382 Bundle bundle = new Bundle();
1383
1384 if (extras == null) extras = "";
1385 Properties extraProp = new Properties();
1386
1387 try {
Jeff Sharkey104344e2011-07-10 14:20:41 -07001388 extraProp.load(new StringReader(extras));
Miguel Torroja1e84da82010-07-27 07:02:24 +02001389 }
1390 catch (IOException e)
1391 {
1392 Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
1393 }
1394
1395 for (Entry<Object, Object> ent : extraProp.entrySet())
1396 {
1397 bundle.putString((String) ent.getKey(), (String) ent.getValue());
1398 }
1399
1400 notification.extras = bundle;
1401
1402 mNIHandler.handleNiNotification(notification);
1403 }
1404
1405 /**
1406 * Called from native code to request set id info.
1407 * We should be careful about receiving null string from the TelephonyManager,
1408 * because sending null String to JNI function would cause a crash.
1409 */
1410
1411 private void requestSetID(int flags) {
1412 TelephonyManager phone = (TelephonyManager)
1413 mContext.getSystemService(Context.TELEPHONY_SERVICE);
1414 int type = AGPS_SETID_TYPE_NONE;
1415 String data = "";
1416
1417 if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
1418 String data_temp = phone.getSubscriberId();
1419 if (data_temp == null) {
1420 // This means the framework does not have the SIM card ready.
1421 } else {
1422 // This means the framework has the SIM card.
1423 data = data_temp;
1424 type = AGPS_SETID_TYPE_IMSI;
1425 }
1426 }
1427 else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
1428 String data_temp = phone.getLine1Number();
1429 if (data_temp == null) {
1430 // This means the framework does not have the SIM card ready.
1431 } else {
1432 // This means the framework has the SIM card.
1433 data = data_temp;
1434 type = AGPS_SETID_TYPE_MSISDN;
1435 }
1436 }
1437 native_agps_set_id(type, data);
1438 }
1439
1440 /**
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001441 * Called from native code to request utc time info
1442 */
1443
1444 private void requestUtcTime() {
1445 sendMessage(INJECT_NTP_TIME, 0, null);
1446 }
1447
1448 /**
Miguel Torroja1e84da82010-07-27 07:02:24 +02001449 * Called from native code to request reference location info
1450 */
1451
1452 private void requestRefLocation(int flags) {
1453 TelephonyManager phone = (TelephonyManager)
1454 mContext.getSystemService(Context.TELEPHONY_SERVICE);
1455 if (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
1456 GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation();
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001457 if ((gsm_cell != null) && (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) &&
1458 (phone.getNetworkOperator() != null) &&
1459 (phone.getNetworkOperator().length() > 3)) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001460 int type;
1461 int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0,3));
1462 int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3));
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001463 int networkType = phone.getNetworkType();
1464 if (networkType == TelephonyManager.NETWORK_TYPE_UMTS
1465 || networkType == TelephonyManager.NETWORK_TYPE_HSDPA
1466 || networkType == TelephonyManager.NETWORK_TYPE_HSUPA
1467 || networkType == TelephonyManager.NETWORK_TYPE_HSPA) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001468 type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001469 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001470 type = AGPS_REF_LOCATION_TYPE_GSM_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001471 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02001472 native_agps_set_ref_location_cellid(type, mcc, mnc,
1473 gsm_cell.getLac(), gsm_cell.getCid());
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001474 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001475 Log.e(TAG,"Error getting cell location info.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001476 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02001477 }
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001478 else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001479 Log.e(TAG,"CDMA not supported.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001480 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02001481 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04001482
Mike Lockwood98e48692010-04-07 16:32:51 -04001483 private void sendMessage(int message, int arg, Object obj) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001484 // hold a wake lock until this message is delivered
Jeff Brown028872f2012-08-25 13:07:01 -07001485 // note that this assumes the message will not be removed from the queue before
1486 // it is handled (otherwise the wake lock would be leaked).
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001487 mWakeLock.acquire();
1488 mHandler.obtainMessage(message, arg, 1, obj).sendToTarget();
Mike Lockwood98e48692010-04-07 16:32:51 -04001489 }
1490
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001491 private final class ProviderHandler extends Handler {
Jeff Brown028872f2012-08-25 13:07:01 -07001492 public ProviderHandler() {
1493 super(true /*async*/);
1494 }
1495
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001496 @Override
Mike Lockwood4a7b65e2010-10-25 16:35:55 -04001497 public void handleMessage(Message msg) {
Mike Lockwood98e48692010-04-07 16:32:51 -04001498 int message = msg.what;
1499 switch (message) {
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001500 case ENABLE:
1501 if (msg.arg1 == 1) {
1502 handleEnable();
1503 } else {
1504 handleDisable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001506 break;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001507 case SET_REQUEST:
1508 GpsRequest gpsRequest = (GpsRequest) msg.obj;
1509 handleSetRequest(gpsRequest.request, gpsRequest.source);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001510 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001511 case UPDATE_NETWORK_STATE:
1512 handleUpdateNetworkState(msg.arg1, (NetworkInfo)msg.obj);
1513 break;
1514 case INJECT_NTP_TIME:
1515 handleInjectNtpTime();
1516 break;
1517 case DOWNLOAD_XTRA_DATA:
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04001518 if (mSupportsXtra) {
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001519 handleDownloadXtraData();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001520 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001521 break;
Kevin Tang40e1baf2012-01-10 14:32:44 -08001522 case INJECT_NTP_TIME_FINISHED:
1523 mInjectNtpTimePending = STATE_IDLE;
1524 break;
1525 case DOWNLOAD_XTRA_DATA_FINISHED:
1526 mDownloadXtraDataPending = STATE_IDLE;
1527 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001528 case UPDATE_LOCATION:
1529 handleUpdateLocation((Location)msg.obj);
1530 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001532 if (msg.arg2 == 1) {
1533 // wakelock was taken for this message, release it
1534 mWakeLock.release();
Mike Lockwood98e48692010-04-07 16:32:51 -04001535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001536 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001537 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001539 private final class NetworkLocationListener implements LocationListener {
1540 @Override
1541 public void onLocationChanged(Location location) {
1542 // this callback happens on mHandler looper
1543 if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
1544 handleUpdateLocation(location);
1545 }
1546 }
1547 @Override
1548 public void onStatusChanged(String provider, int status, Bundle extras) { }
1549 @Override
1550 public void onProviderEnabled(String provider) { }
1551 @Override
1552 public void onProviderDisabled(String provider) { }
1553 }
1554
Kevin Tanga5fe6b22011-06-05 14:25:16 -07001555 private String getSelectedApn() {
1556 Uri uri = Uri.parse("content://telephony/carriers/preferapn");
1557 String apn = null;
1558
1559 Cursor cursor = mContext.getContentResolver().query(uri, new String[] {"apn"},
1560 null, null, Carriers.DEFAULT_SORT_ORDER);
1561
1562 if (null != cursor) {
1563 try {
1564 if (cursor.moveToFirst()) {
1565 apn = cursor.getString(0);
1566 }
1567 } finally {
1568 cursor.close();
1569 }
1570 }
1571 return apn;
1572 }
1573
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001574 @Override
1575 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1576 StringBuilder s = new StringBuilder();
1577 s.append(" mFixInterval=").append(mFixInterval).append("\n");
1578 s.append(" mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities)).append(" (");
1579 if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHED ");
1580 if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
1581 if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA ");
1582 if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT ");
1583 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME ");
1584 s.append(")\n");
1585
1586 s.append(native_get_internal_state());
1587 pw.append(s);
1588 }
1589
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001590 // for GPS SV statistics
1591 private static final int MAX_SVS = 32;
1592 private static final int EPHEMERIS_MASK = 0;
1593 private static final int ALMANAC_MASK = 1;
1594 private static final int USED_FOR_FIX_MASK = 2;
1595
1596 // preallocated arrays, to avoid memory allocation in reportStatus()
1597 private int mSvs[] = new int[MAX_SVS];
1598 private float mSnrs[] = new float[MAX_SVS];
1599 private float mSvElevations[] = new float[MAX_SVS];
1600 private float mSvAzimuths[] = new float[MAX_SVS];
1601 private int mSvMasks[] = new int[3];
1602 private int mSvCount;
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001603 // preallocated to avoid memory allocation in reportNmea()
1604 private byte[] mNmeaBuffer = new byte[120];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001605
1606 static { class_init_native(); }
1607 private static native void class_init_native();
1608 private static native boolean native_is_supported();
1609
1610 private native boolean native_init();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 private native void native_cleanup();
Mike Lockwood04598b62010-04-14 17:17:24 -04001612 private native boolean native_set_position_mode(int mode, int recurrence, int min_interval,
1613 int preferred_accuracy, int preferred_time);
1614 private native boolean native_start();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615 private native boolean native_stop();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001616 private native void native_delete_aiding_data(int flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001617 // returns number of SVs
1618 // mask[0] is ephemeris mask and mask[1] is almanac mask
1619 private native int native_read_sv_status(int[] svs, float[] snrs,
1620 float[] elevations, float[] azimuths, int[] masks);
Mike Lockwoodf602d362010-06-20 14:28:16 -07001621 private native int native_read_nmea(byte[] buffer, int bufferSize);
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -04001622 private native void native_inject_location(double latitude, double longitude, float accuracy);
1623
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06001624 // XTRA Support
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001625 private native void native_inject_time(long time, long timeReference, int uncertainty);
1626 private native boolean native_supports_xtra();
1627 private native void native_inject_xtra_data(byte[] data, int length);
The Android Open Source Project10592532009-03-18 17:39:46 -07001628
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06001629 // DEBUG Support
1630 private native String native_get_internal_state();
1631
1632 // AGPS Support
Mike Lockwoode3635c92009-05-11 08:38:02 -04001633 private native void native_agps_data_conn_open(String apn);
1634 private native void native_agps_data_conn_closed();
1635 private native void native_agps_data_conn_failed();
Miguel Torroja1e84da82010-07-27 07:02:24 +02001636 private native void native_agps_ni_message(byte [] msg, int length);
Mike Lockwooda9e54612009-06-19 14:54:42 -04001637 private native void native_set_agps_server(int type, String hostname, int port);
Danke Xie22d1f9f2009-08-18 18:28:45 -04001638
1639 // Network-initiated (NI) Support
1640 private native void native_send_ni_response(int notificationId, int userResponse);
Miguel Torroja1e84da82010-07-27 07:02:24 +02001641
1642 // AGPS ril suport
1643 private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
1644 int lac, int cid);
1645 private native void native_agps_set_id(int type, String setid);
Mike Lockwood50130bb2010-10-11 06:22:50 -04001646
1647 private native void native_update_network_state(boolean connected, int type,
Kevin Tanga5fe6b22011-06-05 14:25:16 -07001648 boolean roaming, boolean available, String extraInfo, String defaultAPN);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649}