blob: bd7668b75aa038272efcdcabb321ee4c72f0ae46 [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;
32import android.location.LocationManager;
33import android.location.LocationProvider;
Mike Lockwood58bda982009-04-14 16:25:07 -040034import android.net.ConnectivityManager;
Mike Lockwood03d24672009-10-08 15:45:03 -040035import android.net.NetworkInfo;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070036import android.net.Uri;
Mike Lockwood63aa5a62010-04-14 19:21:31 -040037import android.os.Binder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.os.Bundle;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040039import android.os.Handler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.os.IBinder;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040041import android.os.Looper;
42import android.os.Message;
Mike Lockwood0528b9b2009-05-07 10:12:54 -040043import android.os.PowerManager;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040044import android.os.Process;
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 Hackborn7e9f4eb2010-09-10 18:43:00 -070048import android.os.WorkSource;
Mike Lockwoodbcab8df2009-06-25 16:39:09 -040049import android.provider.Settings;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070050import android.provider.Telephony.Carriers;
Miguel Torroja1e84da82010-07-27 07:02:24 +020051import android.provider.Telephony.Sms.Intents;
Jake Hambyb49a73d2011-03-15 20:09:46 -070052import android.telephony.SmsMessage;
Miguel Torroja1e84da82010-07-27 07:02:24 +020053import android.telephony.TelephonyManager;
54import android.telephony.gsm.GsmCellLocation;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.util.Log;
Jeff Sharkey104344e2011-07-10 14:20:41 -070056import android.util.NtpTrustedTime;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -040057import android.util.SparseIntArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058
Mike Lockwood2f82c4e2009-04-17 08:24:10 -040059import com.android.internal.app.IBatteryStats;
Danke Xie22d1f9f2009-08-18 18:28:45 -040060import com.android.internal.location.GpsNetInitiatedHandler;
61import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
Jake Hambyb49a73d2011-03-15 20:09:46 -070062import com.android.internal.telephony.Phone;
Wink Savillea639b312012-07-10 12:37:54 -070063import com.android.internal.telephony.PhoneConstants;
The Android Open Source Project10592532009-03-18 17:39:46 -070064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import java.io.File;
66import java.io.FileInputStream;
67import java.io.IOException;
Jeff Sharkey104344e2011-07-10 14:20:41 -070068import java.io.StringReader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069import java.util.ArrayList;
Mike Lockwoodf1218be2010-01-29 09:20:06 -050070import java.util.Date;
Danke Xie22d1f9f2009-08-18 18:28:45 -040071import java.util.Map.Entry;
Jake Hambyb49a73d2011-03-15 20:09:46 -070072import java.util.Properties;
Mike Lockwood89096312010-03-24 10:14:55 -040073import java.util.concurrent.CountDownLatch;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074
75/**
76 * A GPS implementation of LocationProvider used by LocationManager.
77 *
78 * {@hide}
79 */
Mike Lockwood89096312010-03-24 10:14:55 -040080public class GpsLocationProvider implements LocationProviderInterface {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081
82 private static final String TAG = "GpsLocationProvider";
Mike Lockwood29c84342009-05-06 14:01:15 -040083
Brian Muramatsu1715cb32012-08-08 17:32:21 -070084 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
85 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
Mike Lockwood62a8fc12010-03-22 14:23:26 -040086
The Android Open Source Project10592532009-03-18 17:39:46 -070087 // these need to match GpsPositionMode enum in gps.h
88 private static final int GPS_POSITION_MODE_STANDALONE = 0;
89 private static final int GPS_POSITION_MODE_MS_BASED = 1;
90 private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
91
Mike Lockwood04598b62010-04-14 17:17:24 -040092 // these need to match GpsPositionRecurrence enum in gps.h
93 private static final int GPS_POSITION_RECURRENCE_PERIODIC = 0;
94 private static final int GPS_POSITION_RECURRENCE_SINGLE = 1;
95
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096 // these need to match GpsStatusValue defines in gps.h
97 private static final int GPS_STATUS_NONE = 0;
98 private static final int GPS_STATUS_SESSION_BEGIN = 1;
99 private static final int GPS_STATUS_SESSION_END = 2;
100 private static final int GPS_STATUS_ENGINE_ON = 3;
101 private static final int GPS_STATUS_ENGINE_OFF = 4;
102
Mike Lockwoode3635c92009-05-11 08:38:02 -0400103 // these need to match GpsApgsStatusValue defines in gps.h
104 /** AGPS status event values. */
105 private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
106 private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
107 private static final int GPS_AGPS_DATA_CONNECTED = 3;
108 private static final int GPS_AGPS_DATA_CONN_DONE = 4;
109 private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
Mike Lockwood58bda982009-04-14 16:25:07 -0400110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 // these need to match GpsLocationFlags enum in gps.h
112 private static final int LOCATION_INVALID = 0;
113 private static final int LOCATION_HAS_LAT_LONG = 1;
114 private static final int LOCATION_HAS_ALTITUDE = 2;
115 private static final int LOCATION_HAS_SPEED = 4;
116 private static final int LOCATION_HAS_BEARING = 8;
117 private static final int LOCATION_HAS_ACCURACY = 16;
Mike Lockwoode3635c92009-05-11 08:38:02 -0400118
119// IMPORTANT - the GPS_DELETE_* symbols here must match constants in gps.h
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 private static final int GPS_DELETE_EPHEMERIS = 0x0001;
121 private static final int GPS_DELETE_ALMANAC = 0x0002;
122 private static final int GPS_DELETE_POSITION = 0x0004;
123 private static final int GPS_DELETE_TIME = 0x0008;
124 private static final int GPS_DELETE_IONO = 0x0010;
125 private static final int GPS_DELETE_UTC = 0x0020;
126 private static final int GPS_DELETE_HEALTH = 0x0040;
127 private static final int GPS_DELETE_SVDIR = 0x0080;
128 private static final int GPS_DELETE_SVSTEER = 0x0100;
129 private static final int GPS_DELETE_SADATA = 0x0200;
130 private static final int GPS_DELETE_RTI = 0x0400;
131 private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
132 private static final int GPS_DELETE_ALL = 0xFFFF;
133
Mike Lockwood04598b62010-04-14 17:17:24 -0400134 // The GPS_CAPABILITY_* flags must match the values in gps.h
135 private static final int GPS_CAPABILITY_SCHEDULING = 0x0000001;
136 private static final int GPS_CAPABILITY_MSB = 0x0000002;
137 private static final int GPS_CAPABILITY_MSA = 0x0000004;
138 private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400139 private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010;
Mike Lockwood04598b62010-04-14 17:17:24 -0400140
Mike Lockwoode3635c92009-05-11 08:38:02 -0400141 // these need to match AGpsType enum in gps.h
142 private static final int AGPS_TYPE_SUPL = 1;
143 private static final int AGPS_TYPE_C2K = 2;
144
145 // for mAGpsDataConnectionState
146 private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
147 private static final int AGPS_DATA_CONNECTION_OPENING = 1;
148 private static final int AGPS_DATA_CONNECTION_OPEN = 2;
Mike Lockwood58bda982009-04-14 16:25:07 -0400149
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400150 // Handler messages
151 private static final int CHECK_LOCATION = 1;
152 private static final int ENABLE = 2;
153 private static final int ENABLE_TRACKING = 3;
154 private static final int UPDATE_NETWORK_STATE = 4;
155 private static final int INJECT_NTP_TIME = 5;
156 private static final int DOWNLOAD_XTRA_DATA = 6;
157 private static final int UPDATE_LOCATION = 7;
158 private static final int ADD_LISTENER = 8;
159 private static final int REMOVE_LISTENER = 9;
Mike Lockwood03ca2162010-04-01 08:10:09 -0700160 private static final int REQUEST_SINGLE_SHOT = 10;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400161
Miguel Torroja1e84da82010-07-27 07:02:24 +0200162 // Request setid
163 private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
164 private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2;
165
166 // Request ref location
167 private static final int AGPS_RIL_REQUEST_REFLOC_CELLID = 1;
168 private static final int AGPS_RIL_REQUEST_REFLOC_MAC = 2;
169
170 // ref. location info
171 private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
172 private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
173 private static final int AGPS_REG_LOCATION_TYPE_MAC = 3;
174
175 // set id info
176 private static final int AGPS_SETID_TYPE_NONE = 0;
177 private static final int AGPS_SETID_TYPE_IMSI = 1;
178 private static final int AGPS_SETID_TYPE_MSISDN = 2;
179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180 private static final String PROPERTIES_FILE = "/etc/gps.conf";
181
182 private int mLocationFlags = LOCATION_INVALID;
183
184 // current status
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400185 private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186
187 // time for last status update
188 private long mStatusUpdateTime = SystemClock.elapsedRealtime();
Mike Lockwoodd53ba012010-04-15 20:41:26 -0400189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 // turn off GPS fix icon if we haven't received a fix in 10 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400191 private static final long RECENT_FIX_TIMEOUT = 10 * 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192
Mike Lockwood0632ca72009-05-14 15:51:03 -0400193 // stop trying if we do not receive a fix within 60 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400194 private static final int NO_FIX_TIMEOUT = 60 * 1000;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400195
Nick Pellyb041f232012-05-07 17:12:25 -0700196 // if the fix interval is below this we leave GPS on,
197 // if above then we cycle the GPS driver.
198 // Typical hot TTTF is ~5 seconds, so 10 seconds seems sane.
199 private static final int GPS_POLLING_THRESHOLD_INTERVAL = 10 * 1000;
200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 // true if we are enabled
Mike Lockwood89096312010-03-24 10:14:55 -0400202 private volatile boolean mEnabled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203
204 // true if we have network connectivity
205 private boolean mNetworkAvailable;
206
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400207 // flags to trigger NTP or XTRA data download when network becomes available
208 // initialized to true so we do NTP and XTRA when the network comes up after booting
209 private boolean mInjectNtpTimePending = true;
Mike Lockwood5982bf62011-03-17 14:08:01 -0400210 private boolean mDownloadXtraDataPending = true;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400211
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400212 // set to true if the GPS engine does not do on-demand NTP time requests
213 private boolean mPeriodicTimeInjection;
214
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215 // true if GPS is navigating
216 private boolean mNavigating;
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -0500217
218 // true if GPS engine is on
219 private boolean mEngineOn;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220
Mike Lockwood04598b62010-04-14 17:17:24 -0400221 // requested frequency of fixes, in milliseconds
222 private int mFixInterval = 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223
224 // true if we started navigation
225 private boolean mStarted;
226
Mike Lockwood03ca2162010-04-01 08:10:09 -0700227 // true if single shot request is in progress
228 private boolean mSingleShot;
229
Mike Lockwood04598b62010-04-14 17:17:24 -0400230 // capabilities of the GPS engine
231 private int mEngineCapabilities;
232
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -0400233 // true if XTRA is supported
234 private boolean mSupportsXtra;
235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 // for calculating time to first fix
237 private long mFixRequestTime = 0;
238 // time to first fix for most recent session
239 private int mTTFF = 0;
240 // time we received our last fix
241 private long mLastFixTime;
242
Mike Lockwood04598b62010-04-14 17:17:24 -0400243 private int mPositionMode;
244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245 // properties loaded from PROPERTIES_FILE
246 private Properties mProperties;
Mike Lockwood734d6032009-07-28 18:30:25 -0700247 private String mSuplServerHost;
248 private int mSuplServerPort;
249 private String mC2KServerHost;
250 private int mC2KServerPort;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400252 private final Context mContext;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700253 private final NtpTrustedTime mNtpTime;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400254 private final ILocationManager mLocationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
256 private Bundle mLocationExtras = new Bundle();
257 private ArrayList<Listener> mListeners = new ArrayList<Listener>();
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400258
Mike Lockwood89096312010-03-24 10:14:55 -0400259 // GpsLocationProvider's handler thread
260 private final Thread mThread;
261 // Handler for processing events in mThread.
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400262 private Handler mHandler;
Mike Lockwood89096312010-03-24 10:14:55 -0400263 // Used to signal when our main thread has initialized everything
264 private final CountDownLatch mInitializedLatch = new CountDownLatch(1);
The Android Open Source Project10592532009-03-18 17:39:46 -0700265
Mike Lockwoode3635c92009-05-11 08:38:02 -0400266 private String mAGpsApn;
267 private int mAGpsDataConnectionState;
Stephen Li8efd74d2011-03-01 20:56:00 -0800268 private int mAGpsDataConnectionIpAddr;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400269 private final ConnectivityManager mConnMgr;
Danke Xie22d1f9f2009-08-18 18:28:45 -0400270 private final GpsNetInitiatedHandler mNIHandler;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400271
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400272 // Wakelocks
273 private final static String WAKELOCK_KEY = "GpsLocationProvider";
274 private final PowerManager.WakeLock mWakeLock;
Mike Lockwood98e48692010-04-07 16:32:51 -0400275 // bitfield of pending messages to our Handler
276 // used only for messages that cannot have multiple instances queued
277 private int mPendingMessageBits;
278 // separate counter for ADD_LISTENER and REMOVE_LISTENER messages,
279 // which might have multiple instances queued
280 private int mPendingListenerMessages;
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400281
Mike Lockwood29c84342009-05-06 14:01:15 -0400282 // Alarms
283 private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
Mike Lockwood0632ca72009-05-14 15:51:03 -0400284 private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
Mike Lockwood29c84342009-05-06 14:01:15 -0400285 private final AlarmManager mAlarmManager;
286 private final PendingIntent mWakeupIntent;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400287 private final PendingIntent mTimeoutIntent;
Mike Lockwood29c84342009-05-06 14:01:15 -0400288
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400289 private final IBatteryStats mBatteryStats;
290 private final SparseIntArray mClientUids = new SparseIntArray();
The Android Open Source Project10592532009-03-18 17:39:46 -0700291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 // how often to request NTP time, in milliseconds
Mike Lockwood4c126062011-05-23 20:57:43 -0400293 // current setting 24 hours
294 private static final long NTP_INTERVAL = 24*60*60*1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295 // how long to wait if we have a network error in NTP or XTRA downloading
296 // current setting - 5 minutes
Mike Lockwoodf1218be2010-01-29 09:20:06 -0500297 private static final long RETRY_INTERVAL = 5*60*1000;
298
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400299 private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
300 public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
301 if (listener == null) {
302 throw new NullPointerException("listener is null in addGpsStatusListener");
303 }
304
305 synchronized(mListeners) {
306 IBinder binder = listener.asBinder();
307 int size = mListeners.size();
308 for (int i = 0; i < size; i++) {
309 Listener test = mListeners.get(i);
310 if (binder.equals(test.mListener.asBinder())) {
311 // listener already added
312 return;
313 }
314 }
315
316 Listener l = new Listener(listener);
317 binder.linkToDeath(l, 0);
318 mListeners.add(l);
319 }
320 }
321
322 public void removeGpsStatusListener(IGpsStatusListener listener) {
323 if (listener == null) {
324 throw new NullPointerException("listener is null in addGpsStatusListener");
325 }
326
327 synchronized(mListeners) {
328 IBinder binder = listener.asBinder();
329 Listener l = null;
330 int size = mListeners.size();
331 for (int i = 0; i < size && l == null; i++) {
332 Listener test = mListeners.get(i);
333 if (binder.equals(test.mListener.asBinder())) {
334 l = test;
335 }
336 }
337
338 if (l != null) {
339 mListeners.remove(l);
340 binder.unlinkToDeath(l, 0);
341 }
342 }
343 }
344 };
345
346 public IGpsStatusProvider getGpsStatusProvider() {
347 return mGpsStatusProvider;
348 }
349
Mike Lockwood29c84342009-05-06 14:01:15 -0400350 private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
The Android Open Source Project10592532009-03-18 17:39:46 -0700351 @Override public void onReceive(Context context, Intent intent) {
352 String action = intent.getAction();
353
Mike Lockwood29c84342009-05-06 14:01:15 -0400354 if (action.equals(ALARM_WAKEUP)) {
355 if (DEBUG) Log.d(TAG, "ALARM_WAKEUP");
Mike Lockwood03ca2162010-04-01 08:10:09 -0700356 startNavigating(false);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400357 } else if (action.equals(ALARM_TIMEOUT)) {
358 if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");
359 hibernate();
Miguel Torroja1e84da82010-07-27 07:02:24 +0200360 } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {
361 checkSmsSuplInit(intent);
362 } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
363 checkWapSuplInit(intent);
364 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700365 }
Mike Lockwood29c84342009-05-06 14:01:15 -0400366 };
The Android Open Source Project10592532009-03-18 17:39:46 -0700367
Miguel Torroja1e84da82010-07-27 07:02:24 +0200368 private void checkSmsSuplInit(Intent intent) {
369 SmsMessage[] messages = Intents.getMessagesFromIntent(intent);
370 for (int i=0; i <messages.length; i++) {
371 byte[] supl_init = messages[i].getUserData();
372 native_agps_ni_message(supl_init,supl_init.length);
373 }
374 }
375
376 private void checkWapSuplInit(Intent intent) {
377 byte[] supl_init = (byte[]) intent.getExtra("data");
378 native_agps_ni_message(supl_init,supl_init.length);
379 }
380
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381 public static boolean isSupported() {
382 return native_is_supported();
383 }
384
Mike Lockwood4e50b782009-04-03 08:24:43 -0700385 public GpsLocationProvider(Context context, ILocationManager locationManager) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 mContext = context;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700387 mNtpTime = NtpTrustedTime.getInstance(context);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400388 mLocationManager = locationManager;
Mike Lockwood79e642e2010-03-17 23:19:25 -0400389 mNIHandler = new GpsNetInitiatedHandler(context);
Mike Lockwood63598a02010-02-24 11:52:59 -0500390
391 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400393 // Create a wake lock
394 PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
395 mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
Mike Lockwood98e48692010-04-07 16:32:51 -0400396 mWakeLock.setReferenceCounted(false);
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400397
Mike Lockwood29c84342009-05-06 14:01:15 -0400398 mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
399 mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400400 mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
Mike Lockwood29c84342009-05-06 14:01:15 -0400401
Miguel Torroja1e84da82010-07-27 07:02:24 +0200402 IntentFilter intentFilter = new IntentFilter();
403 intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
404 intentFilter.addDataScheme("sms");
405 intentFilter.addDataAuthority("localhost","7275");
406 context.registerReceiver(mBroadcastReciever, intentFilter);
407
408 intentFilter = new IntentFilter();
409 intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
410 try {
411 intentFilter.addDataType("application/vnd.omaloc-supl-init");
412 } catch (IntentFilter.MalformedMimeTypeException e) {
413 Log.w(TAG, "Malformed SUPL init mime type");
414 }
415 context.registerReceiver(mBroadcastReciever, intentFilter);
416
Mike Lockwood58bda982009-04-14 16:25:07 -0400417 mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
418
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400419 // Battery statistics service to be notified when GPS turns on or off
420 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
421
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 mProperties = new Properties();
423 try {
424 File file = new File(PROPERTIES_FILE);
425 FileInputStream stream = new FileInputStream(file);
426 mProperties.load(stream);
427 stream.close();
Mike Lockwoode3635c92009-05-11 08:38:02 -0400428
Mike Lockwood734d6032009-07-28 18:30:25 -0700429 mSuplServerHost = mProperties.getProperty("SUPL_HOST");
Mike Lockwoode3635c92009-05-11 08:38:02 -0400430 String portString = mProperties.getProperty("SUPL_PORT");
Mike Lockwood734d6032009-07-28 18:30:25 -0700431 if (mSuplServerHost != null && portString != null) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700432 try {
Mike Lockwood734d6032009-07-28 18:30:25 -0700433 mSuplServerPort = Integer.parseInt(portString);
The Android Open Source Project10592532009-03-18 17:39:46 -0700434 } catch (NumberFormatException e) {
Mike Lockwoode3635c92009-05-11 08:38:02 -0400435 Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
436 }
437 }
438
Mike Lockwood734d6032009-07-28 18:30:25 -0700439 mC2KServerHost = mProperties.getProperty("C2K_HOST");
Mike Lockwoode3635c92009-05-11 08:38:02 -0400440 portString = mProperties.getProperty("C2K_PORT");
Mike Lockwood734d6032009-07-28 18:30:25 -0700441 if (mC2KServerHost != null && portString != null) {
Mike Lockwoode3635c92009-05-11 08:38:02 -0400442 try {
Mike Lockwood734d6032009-07-28 18:30:25 -0700443 mC2KServerPort = Integer.parseInt(portString);
Mike Lockwoode3635c92009-05-11 08:38:02 -0400444 } catch (NumberFormatException e) {
445 Log.e(TAG, "unable to parse C2K_PORT: " + portString);
The Android Open Source Project10592532009-03-18 17:39:46 -0700446 }
447 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 } catch (IOException e) {
449 Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
450 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400451
Mike Lockwood89096312010-03-24 10:14:55 -0400452 // wait until we are fully initialized before returning
453 mThread = new GpsLocationProviderThread();
454 mThread.start();
455 while (true) {
456 try {
457 mInitializedLatch.await();
458 break;
459 } catch (InterruptedException e) {
460 Thread.currentThread().interrupt();
461 }
462 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400463 }
464
465 private void initialize() {
466 // register our receiver on our thread rather than the main thread
467 IntentFilter intentFilter = new IntentFilter();
468 intentFilter.addAction(ALARM_WAKEUP);
469 intentFilter.addAction(ALARM_TIMEOUT);
470 mContext.registerReceiver(mBroadcastReciever, intentFilter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800471 }
472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473 /**
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500474 * Returns the name of this provider.
475 */
476 public String getName() {
477 return LocationManager.GPS_PROVIDER;
478 }
479
480 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 * Returns true if the provider requires access to a
482 * data network (e.g., the Internet), false otherwise.
483 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484 public boolean requiresNetwork() {
Mike Lockwooda9e54612009-06-19 14:54:42 -0400485 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 }
487
Mike Lockwood03d24672009-10-08 15:45:03 -0400488 public void updateNetworkState(int state, NetworkInfo info) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400489 sendMessage(UPDATE_NETWORK_STATE, state, info);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400490 }
491
492 private void handleUpdateNetworkState(int state, NetworkInfo info) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493 mNetworkAvailable = (state == LocationProvider.AVAILABLE);
494
Joe Onoratof5d95cb2010-01-07 21:48:32 -0500495 if (DEBUG) {
Mike Lockwood03d24672009-10-08 15:45:03 -0400496 Log.d(TAG, "updateNetworkState " + (mNetworkAvailable ? "available" : "unavailable")
497 + " info: " + info);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800498 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400499
Mike Lockwood50130bb2010-10-11 06:22:50 -0400500 if (info != null) {
Kevin Tanga5fe6b22011-06-05 14:25:16 -0700501 boolean dataEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
502 Settings.Secure.MOBILE_DATA, 1) == 1;
503 boolean networkAvailable = info.isAvailable() && dataEnabled;
504 String defaultApn = getSelectedApn();
505 if (defaultApn == null) {
506 defaultApn = "dummy-apn";
507 }
508
Mike Lockwood50130bb2010-10-11 06:22:50 -0400509 native_update_network_state(info.isConnected(), info.getType(),
Kevin Tanga5fe6b22011-06-05 14:25:16 -0700510 info.isRoaming(), networkAvailable,
511 info.getExtraInfo(), defaultApn);
Mike Lockwood50130bb2010-10-11 06:22:50 -0400512 }
513
Mike Lockwood03d24672009-10-08 15:45:03 -0400514 if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL
515 && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
516 String apnName = info.getExtraInfo();
Stephen Li83b69712011-01-25 18:47:28 -0800517 if (mNetworkAvailable) {
518 if (apnName == null) {
519 /* Assign a dummy value in the case of C2K as otherwise we will have a runtime
520 exception in the following call to native_agps_data_conn_open*/
521 apnName = "dummy-apn";
522 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400523 mAGpsApn = apnName;
Stephen Li8efd74d2011-03-01 20:56:00 -0800524 if (DEBUG) Log.d(TAG, "mAGpsDataConnectionIpAddr " + mAGpsDataConnectionIpAddr);
525 if (mAGpsDataConnectionIpAddr != 0xffffffff) {
526 boolean route_result;
527 if (DEBUG) Log.d(TAG, "call requestRouteToHost");
528 route_result = mConnMgr.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_SUPL,
529 mAGpsDataConnectionIpAddr);
530 if (route_result == false) Log.d(TAG, "call requestRouteToHost failed");
531 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400532 if (DEBUG) Log.d(TAG, "call native_agps_data_conn_open");
533 native_agps_data_conn_open(apnName);
534 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
535 } else {
536 if (DEBUG) Log.d(TAG, "call native_agps_data_conn_failed");
537 mAGpsApn = null;
538 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
539 native_agps_data_conn_failed();
540 }
541 }
542
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400543 if (mNetworkAvailable) {
544 if (mInjectNtpTimePending) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400545 sendMessage(INJECT_NTP_TIME, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400546 }
547 if (mDownloadXtraDataPending) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400548 sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400549 }
550 }
551 }
552
553 private void handleInjectNtpTime() {
554 if (!mNetworkAvailable) {
555 // try again when network is up
556 mInjectNtpTimePending = true;
557 return;
558 }
559 mInjectNtpTimePending = false;
560
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400561 long delay;
562
Jeff Sharkey104344e2011-07-10 14:20:41 -0700563 // force refresh NTP cache when outdated
564 if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
565 mNtpTime.forceRefresh();
566 }
567
568 // only update when NTP time is fresh
569 if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
570 long time = mNtpTime.getCachedNtpTime();
571 long timeReference = mNtpTime.getCachedNtpTimeReference();
572 long certainty = mNtpTime.getCacheCertainty();
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400573 long now = System.currentTimeMillis();
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400574
575 Log.d(TAG, "NTP server returned: "
576 + time + " (" + new Date(time)
577 + ") reference: " + timeReference
578 + " certainty: " + certainty
Mike Lockwood1879d282010-04-15 20:05:24 -0400579 + " system time offset: " + (time - now));
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400580
Jeff Sharkey104344e2011-07-10 14:20:41 -0700581 native_inject_time(time, timeReference, (int) certainty);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400582 delay = NTP_INTERVAL;
583 } else {
584 if (DEBUG) Log.d(TAG, "requestTime failed");
585 delay = RETRY_INTERVAL;
586 }
587
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400588 if (mPeriodicTimeInjection) {
589 // send delayed message for next NTP injection
590 // since this is delayed and not urgent we do not hold a wake lock here
591 mHandler.removeMessages(INJECT_NTP_TIME);
592 mHandler.sendMessageDelayed(Message.obtain(mHandler, INJECT_NTP_TIME), delay);
593 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400594 }
595
596 private void handleDownloadXtraData() {
Mike Lockwood5723dfe2010-08-06 10:06:26 -0400597 if (!mNetworkAvailable) {
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400598 // try again when network is up
599 mDownloadXtraDataPending = true;
600 return;
601 }
602 mDownloadXtraDataPending = false;
603
604
605 GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
606 byte[] data = xtraDownloader.downloadXtraData();
607 if (data != null) {
608 if (DEBUG) {
609 Log.d(TAG, "calling native_inject_xtra_data");
610 }
611 native_inject_xtra_data(data, data.length);
612 } else {
613 // try again later
Mike Lockwood98e48692010-04-07 16:32:51 -0400614 // since this is delayed and not urgent we do not hold a wake lock here
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400615 mHandler.removeMessages(DOWNLOAD_XTRA_DATA);
616 mHandler.sendMessageDelayed(Message.obtain(mHandler, DOWNLOAD_XTRA_DATA), RETRY_INTERVAL);
617 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618 }
619
620 /**
Mike Lockwoodfd6e5f02009-05-21 11:28:20 -0400621 * This is called to inform us when another location provider returns a location.
622 * Someday we might use this for network location injection to aid the GPS
623 */
624 public void updateLocation(Location location) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400625 sendMessage(UPDATE_LOCATION, 0, location);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400626 }
627
628 private void handleUpdateLocation(Location location) {
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -0400629 if (location.hasAccuracy()) {
630 native_inject_location(location.getLatitude(), location.getLongitude(),
631 location.getAccuracy());
632 }
Mike Lockwoodfd6e5f02009-05-21 11:28:20 -0400633 }
634
635 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 * Returns true if the provider requires access to a
637 * satellite-based positioning system (e.g., GPS), false
638 * otherwise.
639 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800640 public boolean requiresSatellite() {
641 return true;
642 }
643
644 /**
645 * Returns true if the provider requires access to an appropriate
646 * cellular network (e.g., to make use of cell tower IDs), false
647 * otherwise.
648 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800649 public boolean requiresCell() {
650 return false;
651 }
652
653 /**
654 * Returns true if the use of this provider may result in a
655 * monetary charge to the user, false if use is free. It is up to
656 * each provider to give accurate information.
657 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800658 public boolean hasMonetaryCost() {
659 return false;
660 }
661
662 /**
663 * Returns true if the provider is able to provide altitude
664 * information, false otherwise. A provider that reports altitude
665 * under most circumstances but may occassionally not report it
666 * should return true.
667 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800668 public boolean supportsAltitude() {
669 return true;
670 }
671
672 /**
673 * Returns true if the provider is able to provide speed
674 * information, false otherwise. A provider that reports speed
675 * under most circumstances but may occassionally not report it
676 * should return true.
677 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678 public boolean supportsSpeed() {
679 return true;
680 }
681
682 /**
683 * Returns true if the provider is able to provide bearing
684 * information, false otherwise. A provider that reports bearing
685 * under most circumstances but may occassionally not report it
686 * should return true.
687 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800688 public boolean supportsBearing() {
689 return true;
690 }
691
692 /**
693 * Returns the power requirement for this provider.
694 *
695 * @return the power requirement for this provider, as one of the
696 * constants Criteria.POWER_REQUIREMENT_*.
697 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800698 public int getPowerRequirement() {
699 return Criteria.POWER_HIGH;
700 }
701
702 /**
Mike Lockwood03ca2162010-04-01 08:10:09 -0700703 * Returns true if this provider meets the given criteria,
704 * false otherwise.
705 */
706 public boolean meetsCriteria(Criteria criteria) {
707 return (criteria.getPowerRequirement() != Criteria.POWER_LOW);
708 }
709
710 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 * Returns the horizontal accuracy of this provider
712 *
713 * @return the accuracy of location from this provider, as one
714 * of the constants Criteria.ACCURACY_*.
715 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 public int getAccuracy() {
717 return Criteria.ACCURACY_FINE;
718 }
719
720 /**
721 * Enables this provider. When enabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -0700722 * must be handled. Hardware may be started up
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800723 * when the provider is enabled.
724 */
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400725 public void enable() {
726 synchronized (mHandler) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400727 sendMessage(ENABLE, 1, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400728 }
729 }
730
731 private void handleEnable() {
732 if (DEBUG) Log.d(TAG, "handleEnable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 if (mEnabled) return;
734 mEnabled = native_init();
735
736 if (mEnabled) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -0400737 mSupportsXtra = native_supports_xtra();
Mike Lockwood734d6032009-07-28 18:30:25 -0700738 if (mSuplServerHost != null) {
739 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
740 }
741 if (mC2KServerHost != null) {
742 native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
743 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744 } else {
745 Log.w(TAG, "Failed to enable location provider");
746 }
747 }
748
749 /**
750 * Disables this provider. When disabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -0700751 * need not be handled. Hardware may be shut
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752 * down while the provider is disabled.
753 */
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400754 public void disable() {
755 synchronized (mHandler) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400756 sendMessage(ENABLE, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400757 }
758 }
759
760 private void handleDisable() {
Mike Lockwood89096312010-03-24 10:14:55 -0400761 if (DEBUG) Log.d(TAG, "handleDisable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800762 if (!mEnabled) return;
763
764 mEnabled = false;
765 stopNavigating();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -0500767 // do this before releasing wakelock
768 native_cleanup();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800769 }
770
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500771 public boolean isEnabled() {
772 return mEnabled;
773 }
774
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800775 public int getStatus(Bundle extras) {
776 if (extras != null) {
777 extras.putInt("satellites", mSvCount);
778 }
779 return mStatus;
780 }
781
782 private void updateStatus(int status, int svCount) {
783 if (status != mStatus || svCount != mSvCount) {
784 mStatus = status;
785 mSvCount = svCount;
786 mLocationExtras.putInt("satellites", svCount);
787 mStatusUpdateTime = SystemClock.elapsedRealtime();
788 }
789 }
790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791 public long getStatusUpdateTime() {
792 return mStatusUpdateTime;
793 }
794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800795 public void enableLocationTracking(boolean enable) {
Mike Lockwood03ca2162010-04-01 08:10:09 -0700796 // FIXME - should set a flag here to avoid race conditions with single shot request
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400797 synchronized (mHandler) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400798 sendMessage(ENABLE_TRACKING, (enable ? 1 : 0), null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400799 }
800 }
801
802 private void handleEnableLocationTracking(boolean enable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800803 if (enable) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804 mTTFF = 0;
805 mLastFixTime = 0;
Mike Lockwood03ca2162010-04-01 08:10:09 -0700806 startNavigating(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807 } else {
Mike Lockwood04598b62010-04-14 17:17:24 -0400808 if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
809 mAlarmManager.cancel(mWakeupIntent);
810 mAlarmManager.cancel(mTimeoutIntent);
811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812 stopNavigating();
813 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800814 }
815
Mike Lockwood03ca2162010-04-01 08:10:09 -0700816 public boolean requestSingleShotFix() {
817 if (mStarted) {
818 // cannot do single shot if already navigating
819 return false;
820 }
821 synchronized (mHandler) {
822 mHandler.removeMessages(REQUEST_SINGLE_SHOT);
823 Message m = Message.obtain(mHandler, REQUEST_SINGLE_SHOT);
824 mHandler.sendMessage(m);
825 }
826 return true;
827 }
828
829 private void handleRequestSingleShot() {
830 mTTFF = 0;
831 mLastFixTime = 0;
832 startNavigating(true);
833 }
834
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700835 public void setMinTime(long minTime, WorkSource ws) {
Joe Onoratof5d95cb2010-01-07 21:48:32 -0500836 if (DEBUG) Log.d(TAG, "setMinTime " + minTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800837
838 if (minTime >= 0) {
Mike Lockwood04598b62010-04-14 17:17:24 -0400839 mFixInterval = (int)minTime;
840
841 if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
842 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
843 mFixInterval, 0, 0)) {
844 Log.e(TAG, "set_position_mode failed in setMinTime()");
845 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800847 }
848 }
849
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -0600850 public String getInternalState() {
Nick Pellyb041f232012-05-07 17:12:25 -0700851 StringBuilder s = new StringBuilder();
852 s.append(" mFixInterval=").append(mFixInterval).append("\n");
853 s.append(" mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities)).append(" (");
854 if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHED ");
855 if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
856 if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA ");
857 if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT ");
858 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME ");
859 s.append(")\n");
860
861 s.append(native_get_internal_state());
862 return s.toString();
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -0600863 }
864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 private final class Listener implements IBinder.DeathRecipient {
866 final IGpsStatusListener mListener;
867
868 int mSensors = 0;
869
870 Listener(IGpsStatusListener listener) {
871 mListener = listener;
872 }
873
874 public void binderDied() {
Joe Onoratof5d95cb2010-01-07 21:48:32 -0500875 if (DEBUG) Log.d(TAG, "GPS status listener died");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876
877 synchronized(mListeners) {
878 mListeners.remove(this);
879 }
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -0700880 if (mListener != null) {
881 mListener.asBinder().unlinkToDeath(this, 0);
882 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 }
884 }
885
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400886 public void addListener(int uid) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400887 synchronized (mWakeLock) {
888 mPendingListenerMessages++;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700889 mWakeLock.acquire();
Mike Lockwood98e48692010-04-07 16:32:51 -0400890 Message m = Message.obtain(mHandler, ADD_LISTENER);
891 m.arg1 = uid;
892 mHandler.sendMessage(m);
893 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400894 }
895
896 private void handleAddListener(int uid) {
Dianne Hackborn2e418422009-06-22 20:00:17 -0700897 synchronized(mListeners) {
898 if (mClientUids.indexOfKey(uid) >= 0) {
899 // Shouldn't be here -- already have this uid.
900 Log.w(TAG, "Duplicate add listener for uid " + uid);
901 return;
902 }
903 mClientUids.put(uid, 0);
904 if (mNavigating) {
905 try {
906 mBatteryStats.noteStartGps(uid);
907 } catch (RemoteException e) {
908 Log.w(TAG, "RemoteException in addListener");
909 }
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400910 }
911 }
912 }
913
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400914 public void removeListener(int uid) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400915 synchronized (mWakeLock) {
916 mPendingListenerMessages++;
917 mWakeLock.acquire();
918 Message m = Message.obtain(mHandler, REMOVE_LISTENER);
919 m.arg1 = uid;
920 mHandler.sendMessage(m);
921 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400922 }
923
924 private void handleRemoveListener(int uid) {
Dianne Hackborn2e418422009-06-22 20:00:17 -0700925 synchronized(mListeners) {
926 if (mClientUids.indexOfKey(uid) < 0) {
927 // Shouldn't be here -- don't have this uid.
928 Log.w(TAG, "Unneeded remove listener for uid " + uid);
929 return;
930 }
931 mClientUids.delete(uid);
932 if (mNavigating) {
933 try {
934 mBatteryStats.noteStopGps(uid);
935 } catch (RemoteException e) {
936 Log.w(TAG, "RemoteException in removeListener");
937 }
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400938 }
939 }
940 }
941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800942 public boolean sendExtraCommand(String command, Bundle extras) {
943
Mike Lockwood63aa5a62010-04-14 19:21:31 -0400944 long identity = Binder.clearCallingIdentity();
945 boolean result = false;
946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 if ("delete_aiding_data".equals(command)) {
Mike Lockwood63aa5a62010-04-14 19:21:31 -0400948 result = deleteAidingData(extras);
949 } else if ("force_time_injection".equals(command)) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400950 sendMessage(INJECT_NTP_TIME, 0, null);
Mike Lockwood63aa5a62010-04-14 19:21:31 -0400951 result = true;
952 } else if ("force_xtra_injection".equals(command)) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -0400953 if (mSupportsXtra) {
Mike Lockwood93bc44d2009-05-20 16:58:22 -0400954 xtraDownloadRequest();
Mike Lockwood63aa5a62010-04-14 19:21:31 -0400955 result = true;
Mike Lockwood93bc44d2009-05-20 16:58:22 -0400956 }
Mike Lockwood63aa5a62010-04-14 19:21:31 -0400957 } else {
958 Log.w(TAG, "sendExtraCommand: unknown command " + command);
Mike Lockwood93bc44d2009-05-20 16:58:22 -0400959 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960
Mike Lockwood63aa5a62010-04-14 19:21:31 -0400961 Binder.restoreCallingIdentity(identity);
962 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800963 }
964
965 private boolean deleteAidingData(Bundle extras) {
966 int flags;
967
968 if (extras == null) {
969 flags = GPS_DELETE_ALL;
970 } else {
971 flags = 0;
972 if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
973 if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
974 if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
975 if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
976 if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
977 if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
978 if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
979 if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
980 if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
981 if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
982 if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
983 if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
984 if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
985 }
986
987 if (flags != 0) {
988 native_delete_aiding_data(flags);
989 return true;
990 }
991
992 return false;
993 }
994
Mike Lockwood03ca2162010-04-01 08:10:09 -0700995 private void startNavigating(boolean singleShot) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800996 if (!mStarted) {
Mike Lockwood29c84342009-05-06 14:01:15 -0400997 if (DEBUG) Log.d(TAG, "startNavigating");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800998 mStarted = true;
Mike Lockwood03ca2162010-04-01 08:10:09 -0700999 mSingleShot = singleShot;
1000 mPositionMode = GPS_POSITION_MODE_STANDALONE;
1001
1002 if (Settings.Secure.getInt(mContext.getContentResolver(),
Mike Lockwood660bbfc2009-08-25 16:01:37 -07001003 Settings.Secure.ASSISTED_GPS_ENABLED, 1) != 0) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07001004 if (singleShot && hasCapability(GPS_CAPABILITY_MSA)) {
1005 mPositionMode = GPS_POSITION_MODE_MS_ASSISTED;
Mike Lockwood8dc16c22010-07-29 11:39:55 -04001006 } else if (hasCapability(GPS_CAPABILITY_MSB)) {
Mike Lockwood03ca2162010-04-01 08:10:09 -07001007 mPositionMode = GPS_POSITION_MODE_MS_BASED;
1008 }
Mike Lockwoodbcab8df2009-06-25 16:39:09 -04001009 }
1010
Mike Lockwood04598b62010-04-14 17:17:24 -04001011 int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
1012 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
1013 interval, 0, 0)) {
1014 mStarted = false;
1015 Log.e(TAG, "set_position_mode failed in startNavigating()");
1016 return;
1017 }
1018 if (!native_start()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019 mStarted = false;
1020 Log.e(TAG, "native_start failed in startNavigating()");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001021 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001022 }
1023
1024 // reset SV count to zero
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001025 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
Mike Lockwood29c84342009-05-06 14:01:15 -04001026 mFixRequestTime = System.currentTimeMillis();
Mike Lockwood04598b62010-04-14 17:17:24 -04001027 if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
1028 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
1029 // and our fix interval is not short
1030 if (mFixInterval >= NO_FIX_TIMEOUT) {
1031 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1032 SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
1033 }
Mike Lockwood0632ca72009-05-14 15:51:03 -04001034 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001035 }
1036 }
1037
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001038 private void stopNavigating() {
Mike Lockwood29c84342009-05-06 14:01:15 -04001039 if (DEBUG) Log.d(TAG, "stopNavigating");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 if (mStarted) {
1041 mStarted = false;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001042 mSingleShot = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001043 native_stop();
1044 mTTFF = 0;
1045 mLastFixTime = 0;
1046 mLocationFlags = LOCATION_INVALID;
1047
1048 // reset SV count to zero
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001049 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001050 }
1051 }
1052
Mike Lockwood0632ca72009-05-14 15:51:03 -04001053 private void hibernate() {
1054 // stop GPS until our next fix interval arrives
1055 stopNavigating();
Mike Lockwood0632ca72009-05-14 15:51:03 -04001056 mAlarmManager.cancel(mTimeoutIntent);
1057 mAlarmManager.cancel(mWakeupIntent);
1058 long now = SystemClock.elapsedRealtime();
1059 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
Mike Lockwood04598b62010-04-14 17:17:24 -04001060 SystemClock.elapsedRealtime() + mFixInterval, mWakeupIntent);
1061 }
1062
1063 private boolean hasCapability(int capability) {
1064 return ((mEngineCapabilities & capability) != 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -04001065 }
1066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001067 /**
1068 * called from native code to update our position.
1069 */
1070 private void reportLocation(int flags, double latitude, double longitude, double altitude,
1071 float speed, float bearing, float accuracy, long timestamp) {
Mike Lockwood29c84342009-05-06 14:01:15 -04001072 if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001073 " timestamp: " + timestamp);
1074
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001075 synchronized (mLocation) {
1076 mLocationFlags = flags;
1077 if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1078 mLocation.setLatitude(latitude);
1079 mLocation.setLongitude(longitude);
1080 mLocation.setTime(timestamp);
Nick Pelly2eeeec22012-07-18 13:13:37 -07001081 // It would be nice to push the elapsed real-time timestamp
1082 // further down the stack, but this is still useful
1083 mLocation.setElapsedRealtimeNano(SystemClock.elapsedRealtimeNano());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 }
1085 if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
1086 mLocation.setAltitude(altitude);
1087 } else {
1088 mLocation.removeAltitude();
1089 }
1090 if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
1091 mLocation.setSpeed(speed);
1092 } else {
1093 mLocation.removeSpeed();
1094 }
1095 if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
1096 mLocation.setBearing(bearing);
1097 } else {
1098 mLocation.removeBearing();
1099 }
1100 if ((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
1101 mLocation.setAccuracy(accuracy);
1102 } else {
1103 mLocation.removeAccuracy();
1104 }
Sean Barbeauced2b2c2011-12-19 04:43:07 -05001105 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001106
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001107 try {
Mike Lockwooda4903f22010-02-17 06:42:23 -05001108 mLocationManager.reportLocation(mLocation, false);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001109 } catch (RemoteException e) {
1110 Log.e(TAG, "RemoteException calling reportLocation");
1111 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112 }
1113
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001114 mLastFixTime = System.currentTimeMillis();
1115 // report time to first fix
1116 if (mTTFF == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1117 mTTFF = (int)(mLastFixTime - mFixRequestTime);
The Android Open Source Projectf4dffd82010-05-06 15:18:59 -07001118 if (DEBUG) Log.d(TAG, "TTFF: " + mTTFF);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001119
1120 // notify status listeners
1121 synchronized(mListeners) {
1122 int size = mListeners.size();
1123 for (int i = 0; i < size; i++) {
1124 Listener listener = mListeners.get(i);
1125 try {
The Android Open Source Projectf4dffd82010-05-06 15:18:59 -07001126 listener.mListener.onFirstFix(mTTFF);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001127 } catch (RemoteException e) {
1128 Log.w(TAG, "RemoteException in stopNavigating");
1129 mListeners.remove(listener);
1130 // adjust for size of list changing
1131 size--;
1132 }
1133 }
1134 }
1135 }
1136
Mike Lockwood03ca2162010-04-01 08:10:09 -07001137 if (mSingleShot) {
1138 stopNavigating();
1139 }
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001140 if (mStarted && mStatus != LocationProvider.AVAILABLE) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001141 // we want to time out if we do not receive a fix
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001142 // within the time out and we are requesting infrequent fixes
Mike Lockwood04598b62010-04-14 17:17:24 -04001143 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001144 mAlarmManager.cancel(mTimeoutIntent);
1145 }
1146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001147 // send an intent to notify that the GPS is receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001148 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1149 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001150 mContext.sendBroadcast(intent);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001151 updateStatus(LocationProvider.AVAILABLE, mSvCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001152 }
Mike Lockwood29c84342009-05-06 14:01:15 -04001153
Nick Pellyb041f232012-05-07 17:12:25 -07001154 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted &&
1155 mFixInterval > GPS_POLLING_THRESHOLD_INTERVAL) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001156 if (DEBUG) Log.d(TAG, "got fix, hibernating");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001157 hibernate();
Mike Lockwood29c84342009-05-06 14:01:15 -04001158 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001159 }
1160
1161 /**
1162 * called from native code to update our status
1163 */
1164 private void reportStatus(int status) {
Mike Lockwoodb8d90332010-10-18 17:59:48 -04001165 if (DEBUG) Log.v(TAG, "reportStatus status: " + status);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001166
Dianne Hackborn2e418422009-06-22 20:00:17 -07001167 synchronized(mListeners) {
1168 boolean wasNavigating = mNavigating;
Mike Lockwooddbd6fd82009-12-07 18:43:36 -05001169
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001170 switch (status) {
1171 case GPS_STATUS_SESSION_BEGIN:
1172 mNavigating = true;
Mike Lockwood271f9f12010-02-02 11:41:52 -05001173 mEngineOn = true;
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001174 break;
1175 case GPS_STATUS_SESSION_END:
1176 mNavigating = false;
1177 break;
1178 case GPS_STATUS_ENGINE_ON:
1179 mEngineOn = true;
1180 break;
1181 case GPS_STATUS_ENGINE_OFF:
1182 mEngineOn = false;
Mike Lockwood271f9f12010-02-02 11:41:52 -05001183 mNavigating = false;
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001184 break;
1185 }
1186
Mike Lockwooddbd6fd82009-12-07 18:43:36 -05001187 if (wasNavigating != mNavigating) {
1188 int size = mListeners.size();
1189 for (int i = 0; i < size; i++) {
1190 Listener listener = mListeners.get(i);
1191 try {
1192 if (mNavigating) {
1193 listener.mListener.onGpsStarted();
1194 } else {
1195 listener.mListener.onGpsStopped();
1196 }
1197 } catch (RemoteException e) {
1198 Log.w(TAG, "RemoteException in reportStatus");
1199 mListeners.remove(listener);
1200 // adjust for size of list changing
1201 size--;
1202 }
1203 }
1204
Dianne Hackborn2e418422009-06-22 20:00:17 -07001205 try {
Mike Lockwooddbd6fd82009-12-07 18:43:36 -05001206 // update battery stats
1207 for (int i=mClientUids.size() - 1; i >= 0; i--) {
1208 int uid = mClientUids.keyAt(i);
1209 if (mNavigating) {
1210 mBatteryStats.noteStartGps(uid);
1211 } else {
1212 mBatteryStats.noteStopGps(uid);
1213 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001214 }
Dianne Hackborn2e418422009-06-22 20:00:17 -07001215 } catch (RemoteException e) {
1216 Log.w(TAG, "RemoteException in reportStatus");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001217 }
Mike Lockwooddbd6fd82009-12-07 18:43:36 -05001218
1219 // send an intent to notify that the GPS has been enabled or disabled.
Mike Lockwood00b74272010-03-26 10:41:48 -04001220 Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
1221 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
Mike Lockwooddbd6fd82009-12-07 18:43:36 -05001222 mContext.sendBroadcast(intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001223 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001224 }
1225 }
1226
1227 /**
1228 * called from native code to update SV info
1229 */
1230 private void reportSvStatus() {
1231
1232 int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
1233
1234 synchronized(mListeners) {
1235 int size = mListeners.size();
1236 for (int i = 0; i < size; i++) {
1237 Listener listener = mListeners.get(i);
1238 try {
1239 listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs,
1240 mSvElevations, mSvAzimuths, mSvMasks[EPHEMERIS_MASK],
1241 mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK]);
1242 } catch (RemoteException e) {
1243 Log.w(TAG, "RemoteException in reportSvInfo");
1244 mListeners.remove(listener);
1245 // adjust for size of list changing
1246 size--;
1247 }
1248 }
1249 }
1250
Mike Lockwood29c84342009-05-06 14:01:15 -04001251 if (VERBOSE) {
1252 Log.v(TAG, "SV count: " + svCount +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001253 " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) +
1254 " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK]));
1255 for (int i = 0; i < svCount; i++) {
Mike Lockwood29c84342009-05-06 14:01:15 -04001256 Log.v(TAG, "sv: " + mSvs[i] +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001257 " snr: " + (float)mSnrs[i]/10 +
1258 " elev: " + mSvElevations[i] +
1259 " azimuth: " + mSvAzimuths[i] +
1260 ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? " " : " E") +
1261 ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? " " : " A") +
1262 ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U"));
1263 }
1264 }
1265
Kevin.KY Tsai0881f4f2010-05-21 15:10:39 -04001266 // return number of sets used in fix instead of total
1267 updateStatus(mStatus, Integer.bitCount(mSvMasks[USED_FOR_FIX_MASK]));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001268
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001269 if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
Mike Lockwood04598b62010-04-14 17:17:24 -04001270 System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001271 // send an intent to notify that the GPS is no longer receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001272 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1273 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001274 mContext.sendBroadcast(intent);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001275 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001276 }
1277 }
Mike Lockwood58bda982009-04-14 16:25:07 -04001278
1279 /**
Mike Lockwoode3635c92009-05-11 08:38:02 -04001280 * called from native code to update AGPS status
Mike Lockwood58bda982009-04-14 16:25:07 -04001281 */
Stephen Li8efd74d2011-03-01 20:56:00 -08001282 private void reportAGpsStatus(int type, int status, int ipaddr) {
Mike Lockwood58bda982009-04-14 16:25:07 -04001283 switch (status) {
Mike Lockwoode3635c92009-05-11 08:38:02 -04001284 case GPS_REQUEST_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001285 if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
Mike Lockwood2acfd342010-09-22 12:13:39 -04001286 // Set mAGpsDataConnectionState before calling startUsingNetworkFeature
1287 // to avoid a race condition with handleUpdateNetworkState()
1288 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
1289 int result = mConnMgr.startUsingNetworkFeature(
Mike Lockwood58bda982009-04-14 16:25:07 -04001290 ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
Stephen Li8efd74d2011-03-01 20:56:00 -08001291 mAGpsDataConnectionIpAddr = ipaddr;
Wink Savillea639b312012-07-10 12:37:54 -07001292 if (result == PhoneConstants.APN_ALREADY_ACTIVE) {
1293 if (DEBUG) Log.d(TAG, "PhoneConstants.APN_ALREADY_ACTIVE");
Mike Lockwoodb362a9a2009-06-22 16:20:39 -04001294 if (mAGpsApn != null) {
Stephen Li8efd74d2011-03-01 20:56:00 -08001295 Log.d(TAG, "mAGpsDataConnectionIpAddr " + mAGpsDataConnectionIpAddr);
1296 if (mAGpsDataConnectionIpAddr != 0xffffffff) {
1297 boolean route_result;
1298 if (DEBUG) Log.d(TAG, "call requestRouteToHost");
1299 route_result = mConnMgr.requestRouteToHost(
1300 ConnectivityManager.TYPE_MOBILE_SUPL,
1301 mAGpsDataConnectionIpAddr);
1302 if (route_result == false) Log.d(TAG, "call requestRouteToHost failed");
1303 }
Mike Lockwoodb362a9a2009-06-22 16:20:39 -04001304 native_agps_data_conn_open(mAGpsApn);
1305 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
1306 } else {
Wink Savillea639b312012-07-10 12:37:54 -07001307 Log.e(TAG, "mAGpsApn not set when receiving PhoneConstants.APN_ALREADY_ACTIVE");
Mike Lockwood2acfd342010-09-22 12:13:39 -04001308 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
Mike Lockwoodb362a9a2009-06-22 16:20:39 -04001309 native_agps_data_conn_failed();
1310 }
Wink Savillea639b312012-07-10 12:37:54 -07001311 } else if (result == PhoneConstants.APN_REQUEST_STARTED) {
1312 if (DEBUG) Log.d(TAG, "PhoneConstants.APN_REQUEST_STARTED");
Mike Lockwood2acfd342010-09-22 12:13:39 -04001313 // Nothing to do here
Mike Lockwood58bda982009-04-14 16:25:07 -04001314 } else {
Mike Lockwoodb8d90332010-10-18 17:59:48 -04001315 if (DEBUG) Log.d(TAG, "startUsingNetworkFeature failed");
Mike Lockwood2acfd342010-09-22 12:13:39 -04001316 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001317 native_agps_data_conn_failed();
Mike Lockwood58bda982009-04-14 16:25:07 -04001318 }
1319 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001320 case GPS_RELEASE_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001321 if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
Mike Lockwoode3635c92009-05-11 08:38:02 -04001322 if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
Mike Lockwood58bda982009-04-14 16:25:07 -04001323 mConnMgr.stopUsingNetworkFeature(
1324 ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
Mike Lockwoode3635c92009-05-11 08:38:02 -04001325 native_agps_data_conn_closed();
1326 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
Mike Lockwood58bda982009-04-14 16:25:07 -04001327 }
1328 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001329 case GPS_AGPS_DATA_CONNECTED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001330 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001331 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001332 case GPS_AGPS_DATA_CONN_DONE:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001333 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
Mike Lockwood58bda982009-04-14 16:25:07 -04001334 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001335 case GPS_AGPS_DATA_CONN_FAILED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001336 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001337 break;
1338 }
1339 }
1340
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001341 /**
1342 * called from native code to report NMEA data received
1343 */
Mike Lockwoodf602d362010-06-20 14:28:16 -07001344 private void reportNmea(long timestamp) {
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001345 synchronized(mListeners) {
1346 int size = mListeners.size();
1347 if (size > 0) {
1348 // don't bother creating the String if we have no listeners
Mike Lockwoodf602d362010-06-20 14:28:16 -07001349 int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001350 String nmea = new String(mNmeaBuffer, 0, length);
1351
1352 for (int i = 0; i < size; i++) {
1353 Listener listener = mListeners.get(i);
1354 try {
1355 listener.mListener.onNmeaReceived(timestamp, nmea);
1356 } catch (RemoteException e) {
1357 Log.w(TAG, "RemoteException in reportNmea");
1358 mListeners.remove(listener);
1359 // adjust for size of list changing
1360 size--;
1361 }
1362 }
1363 }
1364 }
1365 }
1366
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001367 /**
Mike Lockwood04598b62010-04-14 17:17:24 -04001368 * called from native code to inform us what the GPS engine capabilities are
1369 */
1370 private void setEngineCapabilities(int capabilities) {
1371 mEngineCapabilities = capabilities;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001372
1373 if (!hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME) && !mPeriodicTimeInjection) {
1374 mPeriodicTimeInjection = true;
1375 requestUtcTime();
1376 }
Mike Lockwood04598b62010-04-14 17:17:24 -04001377 }
1378
1379 /**
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001380 * called from native code to request XTRA data
1381 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001382 private void xtraDownloadRequest() {
Joe Onoratof5d95cb2010-01-07 21:48:32 -05001383 if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
Mike Lockwood98e48692010-04-07 16:32:51 -04001384 sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385 }
1386
Danke Xie22d1f9f2009-08-18 18:28:45 -04001387 //=============================================================
1388 // NI Client support
Miguel Torroja1e84da82010-07-27 07:02:24 +02001389 //=============================================================
Danke Xie22d1f9f2009-08-18 18:28:45 -04001390 private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001391 // Sends a response for an NI reqeust to HAL.
1392 public boolean sendNiResponse(int notificationId, int userResponse)
1393 {
1394 // TODO Add Permission check
Danke Xie22d1f9f2009-08-18 18:28:45 -04001395
Miguel Torroja1e84da82010-07-27 07:02:24 +02001396 StringBuilder extrasBuf = new StringBuilder();
1397
1398 if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
1399 ", response: " + userResponse);
1400 native_send_ni_response(notificationId, userResponse);
1401 return true;
1402 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04001403 };
1404
1405 public INetInitiatedListener getNetInitiatedListener() {
1406 return mNetInitiatedListener;
1407 }
1408
1409 // Called by JNI function to report an NI request.
Miguel Torroja1e84da82010-07-27 07:02:24 +02001410 public void reportNiNotification(
1411 int notificationId,
1412 int niType,
1413 int notifyFlags,
1414 int timeout,
1415 int defaultResponse,
1416 String requestorId,
1417 String text,
1418 int requestorIdEncoding,
1419 int textEncoding,
1420 String extras // Encoded extra data
Danke Xie22d1f9f2009-08-18 18:28:45 -04001421 )
Miguel Torroja1e84da82010-07-27 07:02:24 +02001422 {
1423 Log.i(TAG, "reportNiNotification: entered");
1424 Log.i(TAG, "notificationId: " + notificationId +
1425 ", niType: " + niType +
1426 ", notifyFlags: " + notifyFlags +
1427 ", timeout: " + timeout +
1428 ", defaultResponse: " + defaultResponse);
1429
1430 Log.i(TAG, "requestorId: " + requestorId +
1431 ", text: " + text +
1432 ", requestorIdEncoding: " + requestorIdEncoding +
1433 ", textEncoding: " + textEncoding);
1434
1435 GpsNiNotification notification = new GpsNiNotification();
1436
1437 notification.notificationId = notificationId;
1438 notification.niType = niType;
1439 notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
1440 notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
1441 notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
1442 notification.timeout = timeout;
1443 notification.defaultResponse = defaultResponse;
1444 notification.requestorId = requestorId;
1445 notification.text = text;
1446 notification.requestorIdEncoding = requestorIdEncoding;
1447 notification.textEncoding = textEncoding;
1448
1449 // Process extras, assuming the format is
1450 // one of more lines of "key = value"
1451 Bundle bundle = new Bundle();
1452
1453 if (extras == null) extras = "";
1454 Properties extraProp = new Properties();
1455
1456 try {
Jeff Sharkey104344e2011-07-10 14:20:41 -07001457 extraProp.load(new StringReader(extras));
Miguel Torroja1e84da82010-07-27 07:02:24 +02001458 }
1459 catch (IOException e)
1460 {
1461 Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
1462 }
1463
1464 for (Entry<Object, Object> ent : extraProp.entrySet())
1465 {
1466 bundle.putString((String) ent.getKey(), (String) ent.getValue());
1467 }
1468
1469 notification.extras = bundle;
1470
1471 mNIHandler.handleNiNotification(notification);
1472 }
1473
1474 /**
1475 * Called from native code to request set id info.
1476 * We should be careful about receiving null string from the TelephonyManager,
1477 * because sending null String to JNI function would cause a crash.
1478 */
1479
1480 private void requestSetID(int flags) {
1481 TelephonyManager phone = (TelephonyManager)
1482 mContext.getSystemService(Context.TELEPHONY_SERVICE);
1483 int type = AGPS_SETID_TYPE_NONE;
1484 String data = "";
1485
1486 if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
1487 String data_temp = phone.getSubscriberId();
1488 if (data_temp == null) {
1489 // This means the framework does not have the SIM card ready.
1490 } else {
1491 // This means the framework has the SIM card.
1492 data = data_temp;
1493 type = AGPS_SETID_TYPE_IMSI;
1494 }
1495 }
1496 else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
1497 String data_temp = phone.getLine1Number();
1498 if (data_temp == null) {
1499 // This means the framework does not have the SIM card ready.
1500 } else {
1501 // This means the framework has the SIM card.
1502 data = data_temp;
1503 type = AGPS_SETID_TYPE_MSISDN;
1504 }
1505 }
1506 native_agps_set_id(type, data);
1507 }
1508
1509 /**
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001510 * Called from native code to request utc time info
1511 */
1512
1513 private void requestUtcTime() {
1514 sendMessage(INJECT_NTP_TIME, 0, null);
1515 }
1516
1517 /**
Miguel Torroja1e84da82010-07-27 07:02:24 +02001518 * Called from native code to request reference location info
1519 */
1520
1521 private void requestRefLocation(int flags) {
1522 TelephonyManager phone = (TelephonyManager)
1523 mContext.getSystemService(Context.TELEPHONY_SERVICE);
1524 if (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
1525 GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation();
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001526 if ((gsm_cell != null) && (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) &&
1527 (phone.getNetworkOperator() != null) &&
1528 (phone.getNetworkOperator().length() > 3)) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001529 int type;
1530 int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0,3));
1531 int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3));
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001532 int networkType = phone.getNetworkType();
1533 if (networkType == TelephonyManager.NETWORK_TYPE_UMTS
1534 || networkType == TelephonyManager.NETWORK_TYPE_HSDPA
1535 || networkType == TelephonyManager.NETWORK_TYPE_HSUPA
1536 || networkType == TelephonyManager.NETWORK_TYPE_HSPA) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001537 type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001538 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001539 type = AGPS_REF_LOCATION_TYPE_GSM_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001540 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02001541 native_agps_set_ref_location_cellid(type, mcc, mnc,
1542 gsm_cell.getLac(), gsm_cell.getCid());
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001543 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001544 Log.e(TAG,"Error getting cell location info.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001545 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02001546 }
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001547 else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001548 Log.e(TAG,"CDMA not supported.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001549 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02001550 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04001551
Mike Lockwood98e48692010-04-07 16:32:51 -04001552 private void sendMessage(int message, int arg, Object obj) {
1553 // hold a wake lock while messages are pending
1554 synchronized (mWakeLock) {
1555 mPendingMessageBits |= (1 << message);
1556 mWakeLock.acquire();
1557 mHandler.removeMessages(message);
1558 Message m = Message.obtain(mHandler, message);
1559 m.arg1 = arg;
1560 m.obj = obj;
1561 mHandler.sendMessage(m);
1562 }
1563 }
1564
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001565 private final class ProviderHandler extends Handler {
1566 @Override
Mike Lockwood4a7b65e2010-10-25 16:35:55 -04001567 public void handleMessage(Message msg) {
Mike Lockwood98e48692010-04-07 16:32:51 -04001568 int message = msg.what;
1569 switch (message) {
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001570 case ENABLE:
1571 if (msg.arg1 == 1) {
1572 handleEnable();
1573 } else {
1574 handleDisable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001576 break;
1577 case ENABLE_TRACKING:
1578 handleEnableLocationTracking(msg.arg1 == 1);
1579 break;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001580 case REQUEST_SINGLE_SHOT:
1581 handleRequestSingleShot();
1582 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001583 case UPDATE_NETWORK_STATE:
1584 handleUpdateNetworkState(msg.arg1, (NetworkInfo)msg.obj);
1585 break;
1586 case INJECT_NTP_TIME:
1587 handleInjectNtpTime();
1588 break;
1589 case DOWNLOAD_XTRA_DATA:
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04001590 if (mSupportsXtra) {
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001591 handleDownloadXtraData();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001593 break;
1594 case UPDATE_LOCATION:
1595 handleUpdateLocation((Location)msg.obj);
1596 break;
1597 case ADD_LISTENER:
1598 handleAddListener(msg.arg1);
1599 break;
1600 case REMOVE_LISTENER:
1601 handleRemoveListener(msg.arg1);
1602 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001603 }
Mike Lockwood98e48692010-04-07 16:32:51 -04001604 // release wake lock if no messages are pending
1605 synchronized (mWakeLock) {
1606 mPendingMessageBits &= ~(1 << message);
1607 if (message == ADD_LISTENER || message == REMOVE_LISTENER) {
1608 mPendingListenerMessages--;
1609 }
1610 if (mPendingMessageBits == 0 && mPendingListenerMessages == 0) {
1611 mWakeLock.release();
1612 }
1613 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001615 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001616
Mike Lockwood89096312010-03-24 10:14:55 -04001617 private final class GpsLocationProviderThread extends Thread {
1618
1619 public GpsLocationProviderThread() {
1620 super("GpsLocationProvider");
1621 }
1622
1623 public void run() {
1624 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
1625 initialize();
1626 Looper.prepare();
1627 mHandler = new ProviderHandler();
1628 // signal when we are initialized and ready to go
1629 mInitializedLatch.countDown();
1630 Looper.loop();
1631 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001632 }
1633
Kevin Tanga5fe6b22011-06-05 14:25:16 -07001634 private String getSelectedApn() {
1635 Uri uri = Uri.parse("content://telephony/carriers/preferapn");
1636 String apn = null;
1637
1638 Cursor cursor = mContext.getContentResolver().query(uri, new String[] {"apn"},
1639 null, null, Carriers.DEFAULT_SORT_ORDER);
1640
1641 if (null != cursor) {
1642 try {
1643 if (cursor.moveToFirst()) {
1644 apn = cursor.getString(0);
1645 }
1646 } finally {
1647 cursor.close();
1648 }
1649 }
1650 return apn;
1651 }
1652
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001653 // for GPS SV statistics
1654 private static final int MAX_SVS = 32;
1655 private static final int EPHEMERIS_MASK = 0;
1656 private static final int ALMANAC_MASK = 1;
1657 private static final int USED_FOR_FIX_MASK = 2;
1658
1659 // preallocated arrays, to avoid memory allocation in reportStatus()
1660 private int mSvs[] = new int[MAX_SVS];
1661 private float mSnrs[] = new float[MAX_SVS];
1662 private float mSvElevations[] = new float[MAX_SVS];
1663 private float mSvAzimuths[] = new float[MAX_SVS];
1664 private int mSvMasks[] = new int[3];
1665 private int mSvCount;
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001666 // preallocated to avoid memory allocation in reportNmea()
1667 private byte[] mNmeaBuffer = new byte[120];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668
1669 static { class_init_native(); }
1670 private static native void class_init_native();
1671 private static native boolean native_is_supported();
1672
1673 private native boolean native_init();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001674 private native void native_cleanup();
Mike Lockwood04598b62010-04-14 17:17:24 -04001675 private native boolean native_set_position_mode(int mode, int recurrence, int min_interval,
1676 int preferred_accuracy, int preferred_time);
1677 private native boolean native_start();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001678 private native boolean native_stop();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 private native void native_delete_aiding_data(int flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001680 // returns number of SVs
1681 // mask[0] is ephemeris mask and mask[1] is almanac mask
1682 private native int native_read_sv_status(int[] svs, float[] snrs,
1683 float[] elevations, float[] azimuths, int[] masks);
Mike Lockwoodf602d362010-06-20 14:28:16 -07001684 private native int native_read_nmea(byte[] buffer, int bufferSize);
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -04001685 private native void native_inject_location(double latitude, double longitude, float accuracy);
1686
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06001687 // XTRA Support
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 private native void native_inject_time(long time, long timeReference, int uncertainty);
1689 private native boolean native_supports_xtra();
1690 private native void native_inject_xtra_data(byte[] data, int length);
The Android Open Source Project10592532009-03-18 17:39:46 -07001691
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06001692 // DEBUG Support
1693 private native String native_get_internal_state();
1694
1695 // AGPS Support
Mike Lockwoode3635c92009-05-11 08:38:02 -04001696 private native void native_agps_data_conn_open(String apn);
1697 private native void native_agps_data_conn_closed();
1698 private native void native_agps_data_conn_failed();
Miguel Torroja1e84da82010-07-27 07:02:24 +02001699 private native void native_agps_ni_message(byte [] msg, int length);
Mike Lockwooda9e54612009-06-19 14:54:42 -04001700 private native void native_set_agps_server(int type, String hostname, int port);
Danke Xie22d1f9f2009-08-18 18:28:45 -04001701
1702 // Network-initiated (NI) Support
1703 private native void native_send_ni_response(int notificationId, int userResponse);
Miguel Torroja1e84da82010-07-27 07:02:24 +02001704
1705 // AGPS ril suport
1706 private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
1707 int lac, int cid);
1708 private native void native_agps_set_id(int type, String setid);
Mike Lockwood50130bb2010-10-11 06:22:50 -04001709
1710 private native void native_update_network_state(boolean connected, int type,
Kevin Tanga5fe6b22011-06-05 14:25:16 -07001711 boolean roaming, boolean available, String extraInfo, String defaultAPN);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001712}