19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1700b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwoodpackage com.android.server.location;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1929c84340a14e70419449628ab193d11b7a609e9aMike Lockwoodimport android.app.AlarmManager;
2029c84340a14e70419449628ab193d11b7a609e9aMike Lockwoodimport android.app.PendingIntent;
21105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.content.BroadcastReceiver;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
24105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.content.IntentFilter;
25a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tangimport android.database.Cursor;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Criteria;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.IGpsStatusListener;
2815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwoodimport android.location.IGpsStatusProvider;
294e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwoodimport android.location.ILocationManager;
3022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport android.location.INetInitiatedListener;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Location;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationManager;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationProvider;
3458bda987665af759c379cd494ff4873ac61acf29Mike Lockwoodimport android.net.ConnectivityManager;
3503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwoodimport android.net.NetworkInfo;
36a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tangimport android.net.Uri;
3763aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwoodimport android.os.Binder;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
3962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwoodimport android.os.Handler;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
4162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwoodimport android.os.Looper;
4262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwoodimport android.os.Message;
430528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwoodimport android.os.PowerManager;
4462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwoodimport android.os.Process;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
462f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport android.os.ServiceManager;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
487e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackbornimport android.os.WorkSource;
49bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwoodimport android.provider.Settings;
50a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tangimport android.provider.Telephony.Carriers;
511e84da822e7aa4d494b31c8759917d2751611f84Miguel Torrojaimport android.provider.Telephony.Sms.Intents;
52b49a73dfc4c9817bba1f227e9330555acdf9b56fJake Hambyimport android.telephony.SmsMessage;
531e84da822e7aa4d494b31c8759917d2751611f84Miguel Torrojaimport android.telephony.TelephonyManager;
541e84da822e7aa4d494b31c8759917d2751611f84Miguel Torrojaimport android.telephony.gsm.GsmCellLocation;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
56104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkeyimport android.util.NtpTrustedTime;
572f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport android.util.SparseIntArray;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
592f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport com.android.internal.app.IBatteryStats;
6022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport com.android.internal.location.GpsNetInitiatedHandler;
6122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
62b49a73dfc4c9817bba1f227e9330555acdf9b56fJake Hambyimport com.android.internal.telephony.Phone;
63105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileInputStream;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
67104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkeyimport java.io.StringReader;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
69f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwoodimport java.util.Date;
7022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport java.util.Map.Entry;
71b49a73dfc4c9817bba1f227e9330555acdf9b56fJake Hambyimport java.util.Properties;
7289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwoodimport java.util.concurrent.CountDownLatch;
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A GPS implementation of LocationProvider used by LocationManager.
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
7989096317104722219f73a5c3cc424e6e98c90a61Mike Lockwoodpublic class GpsLocationProvider implements LocationProviderInterface {
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "GpsLocationProvider";
8229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
834a7b65e0d544ef1feff8e1e5789f469f89ebb85cMike Lockwood    private static final boolean DEBUG = false;
8429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private static final boolean VERBOSE = false;
8562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
86105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    // these need to match GpsPositionMode enum in gps.h
87105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_STANDALONE = 0;
88105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_MS_BASED = 1;
89105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
90105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
9104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // these need to match GpsPositionRecurrence enum in gps.h
9204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_POSITION_RECURRENCE_PERIODIC = 0;
9304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_POSITION_RECURRENCE_SINGLE = 1;
9404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these need to match GpsStatusValue defines in gps.h
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_NONE = 0;
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_SESSION_BEGIN = 1;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_SESSION_END = 2;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_ENGINE_ON = 3;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_ENGINE_OFF = 4;
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
102e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // these need to match GpsApgsStatusValue defines in gps.h
103e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    /** AGPS status event values. */
104e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
105e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
106e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONNECTED = 3;
107e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONN_DONE = 4;
108e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
10958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these need to match GpsLocationFlags enum in gps.h
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_INVALID = 0;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_LAT_LONG = 1;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_ALTITUDE = 2;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_SPEED = 4;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_BEARING = 8;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_ACCURACY = 16;
117e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
118e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood// IMPORTANT - the GPS_DELETE_* symbols here must match constants in gps.h
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_EPHEMERIS = 0x0001;
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_ALMANAC = 0x0002;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_POSITION = 0x0004;
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_TIME = 0x0008;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_IONO = 0x0010;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_UTC = 0x0020;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_HEALTH = 0x0040;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SVDIR = 0x0080;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SVSTEER = 0x0100;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SADATA = 0x0200;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_RTI = 0x0400;
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_ALL = 0xFFFF;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // The GPS_CAPABILITY_* flags must match the values in gps.h
13404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_SCHEDULING = 0x0000001;
13504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_MSB = 0x0000002;
13604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_MSA = 0x0000004;
13704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
1389b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010;
13904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
140e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // these need to match AGpsType enum in gps.h
141e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_TYPE_SUPL = 1;
142e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_TYPE_C2K = 2;
143e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
144e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // for mAGpsDataConnectionState
145e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
146e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_OPENING = 1;
147e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_OPEN = 2;
14858bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
14962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    // Handler messages
15062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int CHECK_LOCATION = 1;
15162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int ENABLE = 2;
15262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int ENABLE_TRACKING = 3;
15362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int UPDATE_NETWORK_STATE = 4;
15462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int INJECT_NTP_TIME = 5;
15562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int DOWNLOAD_XTRA_DATA = 6;
15662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int UPDATE_LOCATION = 7;
15762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int ADD_LISTENER = 8;
15862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int REMOVE_LISTENER = 9;
15903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private static final int REQUEST_SINGLE_SHOT = 10;
16062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
1611e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // Request setid
1621e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
1631e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2;
1641e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
1651e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // Request ref location
1661e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_RIL_REQUEST_REFLOC_CELLID = 1;
1671e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_RIL_REQUEST_REFLOC_MAC = 2;
1681e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
1691e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // ref. location info
1701e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
1711e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
1721e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_REG_LOCATION_TYPE_MAC        = 3;
1731e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
1741e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // set id info
1751e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_SETID_TYPE_NONE = 0;
1761e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_SETID_TYPE_IMSI = 1;
1771e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_SETID_TYPE_MSISDN = 2;
1781e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String PROPERTIES_FILE = "/etc/gps.conf";
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mLocationFlags = LOCATION_INVALID;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current status
18415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time for last status update
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mStatusUpdateTime = SystemClock.elapsedRealtime();
188d53ba017ee2381383b4bb4d92e6e0e661431660fMike Lockwood
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // turn off GPS fix icon if we haven't received a fix in 10 seconds
19004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final long RECENT_FIX_TIMEOUT = 10 * 1000;
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1920632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    // stop trying if we do not receive a fix within 60 seconds
19304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int NO_FIX_TIMEOUT = 60 * 1000;
1940632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
195b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly    // if the fix interval is below this we leave GPS on,
196b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly    // if above then we cycle the GPS driver.
197b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly    // Typical hot TTTF is ~5 seconds, so 10 seconds seems sane.
198b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly    private static final int GPS_POLLING_THRESHOLD_INTERVAL = 10 * 1000;
199b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we are enabled
20189096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private volatile boolean mEnabled;
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we have network connectivity
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNetworkAvailable;
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    // flags to trigger NTP or XTRA data download when network becomes available
20762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    // initialized to true so we do NTP and XTRA when the network comes up after booting
20862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private boolean mInjectNtpTimePending = true;
2095982bf66d4fdea38105d91ff0f9d38660ac87581Mike Lockwood    private boolean mDownloadXtraDataPending = true;
21062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
2119b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    // set to true if the GPS engine does not do on-demand NTP time requests
2129b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    private boolean mPeriodicTimeInjection;
2139b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if GPS is navigating
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNavigating;
216cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood
217cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood    // true if GPS engine is on
218cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood    private boolean mEngineOn;
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // requested frequency of fixes, in milliseconds
22104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private int mFixInterval = 1000;
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we started navigation
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mStarted;
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    // true if single shot request is in progress
22703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private boolean mSingleShot;
22803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
22904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // capabilities of the GPS engine
23004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private int mEngineCapabilities;
23104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
2321a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood    // true if XTRA is supported
2331a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood    private boolean mSupportsXtra;
2341a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for calculating time to first fix
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mFixRequestTime = 0;
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time to first fix for most recent session
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mTTFF = 0;
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time we received our last fix
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mLastFixTime;
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private int mPositionMode;
24304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // properties loaded from PROPERTIES_FILE
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Properties mProperties;
246734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private String mSuplServerHost;
247734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private int mSuplServerPort;
248734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private String mC2KServerHost;
249734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private int mC2KServerPort;
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final Context mContext;
252104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey    private final NtpTrustedTime mNtpTime;
25315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final ILocationManager mLocationManager;
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Bundle mLocationExtras = new Bundle();
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<Listener> mListeners = new ArrayList<Listener>();
25762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
25889096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    // GpsLocationProvider's handler thread
25989096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private final Thread mThread;
26089096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    // Handler for processing events in mThread.
26162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private Handler mHandler;
26289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    // Used to signal when our main thread has initialized everything
26389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private final CountDownLatch mInitializedLatch = new CountDownLatch(1);
264105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
265e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private String mAGpsApn;
266e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private int mAGpsDataConnectionState;
2678efd74dbedb65f69734318d9d6be70767f30b57aStephen Li    private int mAGpsDataConnectionIpAddr;
2682f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final ConnectivityManager mConnMgr;
26922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private final GpsNetInitiatedHandler mNIHandler;
2702f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
2710528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    // Wakelocks
2720528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final static String WAKELOCK_KEY = "GpsLocationProvider";
2730528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final PowerManager.WakeLock mWakeLock;
27498e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // bitfield of pending messages to our Handler
27598e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // used only for messages that cannot have multiple instances queued
27698e48691f738680fe59e7383a41458e7337daccdMike Lockwood    private int mPendingMessageBits;
27798e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // separate counter for ADD_LISTENER and REMOVE_LISTENER messages,
27898e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // which might have multiple instances queued
27998e48691f738680fe59e7383a41458e7337daccdMike Lockwood    private int mPendingListenerMessages;
2800528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
28129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    // Alarms
28229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
2830632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
28429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final AlarmManager mAlarmManager;
28529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final PendingIntent mWakeupIntent;
2860632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final PendingIntent mTimeoutIntent;
28729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
2882f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final IBatteryStats mBatteryStats;
2892f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final SparseIntArray mClientUids = new SparseIntArray();
290105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // how often to request NTP time, in milliseconds
2924c126068527c9adba45aa227d40e245ee8e7c9a4Mike Lockwood    // current setting 24 hours
2934c126068527c9adba45aa227d40e245ee8e7c9a4Mike Lockwood    private static final long NTP_INTERVAL = 24*60*60*1000;
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // how long to wait if we have a network error in NTP or XTRA downloading
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current setting - 5 minutes
296f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood    private static final long RETRY_INTERVAL = 5*60*1000;
297f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood
29815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
29915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
30015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
30115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
30215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
30315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
30415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            synchronized(mListeners) {
30515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
30615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
30715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size; i++) {
30815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
30915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
31015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        // listener already added
31115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        return;
31215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
31315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
31415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
31515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = new Listener(listener);
31615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                binder.linkToDeath(l, 0);
31715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                mListeners.add(l);
31815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
31915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
32015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
32115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void removeGpsStatusListener(IGpsStatusListener listener) {
32215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
32315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
32415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
32515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
32615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            synchronized(mListeners) {
32715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
32815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = null;
32915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
33015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size && l == null; i++) {
33115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
33215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
33315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        l = test;
33415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
33515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
33615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
33715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                if (l != null) {
33815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    mListeners.remove(l);
33915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    binder.unlinkToDeath(l, 0);
34015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
34115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
34215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
34315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    };
34415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
34515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    public IGpsStatusProvider getGpsStatusProvider() {
34615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        return mGpsStatusProvider;
34715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
34815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
34929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
350105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        @Override public void onReceive(Context context, Intent intent) {
351105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            String action = intent.getAction();
352105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
35329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (action.equals(ALARM_WAKEUP)) {
35429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_WAKEUP");
35503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                startNavigating(false);
3560632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            } else if (action.equals(ALARM_TIMEOUT)) {
3570632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");
3580632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                hibernate();
3591e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {
3601e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                checkSmsSuplInit(intent);
3611e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
3621e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                checkWapSuplInit(intent);
3631e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja             }
364105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
36529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    };
366105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
3671e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void checkSmsSuplInit(Intent intent) {
3681e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        SmsMessage[] messages = Intents.getMessagesFromIntent(intent);
3691e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        for (int i=0; i <messages.length; i++) {
3701e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            byte[] supl_init = messages[i].getUserData();
3711e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            native_agps_ni_message(supl_init,supl_init.length);
3721e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
3731e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
3741e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
3751e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void checkWapSuplInit(Intent intent) {
3761e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        byte[] supl_init = (byte[]) intent.getExtra("data");
3771e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        native_agps_ni_message(supl_init,supl_init.length);
3781e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
3791e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean isSupported() {
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_is_supported();
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3844e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    public GpsLocationProvider(Context context, ILocationManager locationManager) {
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
386104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey        mNtpTime = NtpTrustedTime.getInstance(context);
38715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mLocationManager = locationManager;
38879e642e8ed75033eacc461633a8f4cd5157d25dfMike Lockwood        mNIHandler = new GpsNetInitiatedHandler(context);
38963598a0619776b421f27cd12fb29eb83dc327997Mike Lockwood
39063598a0619776b421f27cd12fb29eb83dc327997Mike Lockwood        mLocation.setExtras(mLocationExtras);
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3920528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // Create a wake lock
3930528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
3940528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
39598e48691f738680fe59e7383a41458e7337daccdMike Lockwood        mWakeLock.setReferenceCounted(false);
3960528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
39729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
39829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
3990632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
40029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
4011e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        IntentFilter intentFilter = new IntentFilter();
4021e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
4031e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter.addDataScheme("sms");
4041e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter.addDataAuthority("localhost","7275");
4051e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        context.registerReceiver(mBroadcastReciever, intentFilter);
4061e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
4071e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter = new IntentFilter();
4081e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
4091e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        try {
4101e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            intentFilter.addDataType("application/vnd.omaloc-supl-init");
4111e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        } catch (IntentFilter.MalformedMimeTypeException e) {
4121e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            Log.w(TAG, "Malformed SUPL init mime type");
4131e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
4141e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        context.registerReceiver(mBroadcastReciever, intentFilter);
4151e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
41658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
41758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
4182f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        // Battery statistics service to be notified when GPS turns on or off
4192f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
4202f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProperties = new Properties();
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            File file = new File(PROPERTIES_FILE);
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            FileInputStream stream = new FileInputStream(file);
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProperties.load(stream);
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stream.close();
427e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
428734d6031a662a275ec68627bd1258159041d44deMike Lockwood            mSuplServerHost = mProperties.getProperty("SUPL_HOST");
429e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            String portString = mProperties.getProperty("SUPL_PORT");
430734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mSuplServerHost != null && portString != null) {
431105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                try {
432734d6031a662a275ec68627bd1258159041d44deMike Lockwood                    mSuplServerPort = Integer.parseInt(portString);
433105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                } catch (NumberFormatException e) {
434e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
435e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                }
436e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            }
437e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
438734d6031a662a275ec68627bd1258159041d44deMike Lockwood            mC2KServerHost = mProperties.getProperty("C2K_HOST");
439e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            portString = mProperties.getProperty("C2K_PORT");
440734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mC2KServerHost != null && portString != null) {
441e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                try {
442734d6031a662a275ec68627bd1258159041d44deMike Lockwood                    mC2KServerPort = Integer.parseInt(portString);
443e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                } catch (NumberFormatException e) {
444e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse C2K_PORT: " + portString);
445105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                }
446105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
45062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
45189096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        // wait until we are fully initialized before returning
45289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        mThread = new GpsLocationProviderThread();
45389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        mThread.start();
45489096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        while (true) {
45589096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            try {
45689096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood                mInitializedLatch.await();
45789096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood                break;
45889096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            } catch (InterruptedException e) {
45989096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood                Thread.currentThread().interrupt();
46089096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            }
46189096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        }
46262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
46362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
46462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void initialize() {
46562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        // register our receiver on our thread rather than the main thread
46662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        IntentFilter intentFilter = new IntentFilter();
46762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        intentFilter.addAction(ALARM_WAKEUP);
46862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        intentFilter.addAction(ALARM_TIMEOUT);
46962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mContext.registerReceiver(mBroadcastReciever, intentFilter);
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
473d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood     * Returns the name of this provider.
474d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood     */
475d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    public String getName() {
476d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        return LocationManager.GPS_PROVIDER;
477d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    }
478d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood
479d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    /**
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to a
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * data network (e.g., the Internet), false otherwise.
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresNetwork() {
484a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood        return true;
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
48703d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood    public void updateNetworkState(int state, NetworkInfo info) {
48898e48691f738680fe59e7383a41458e7337daccdMike Lockwood        sendMessage(UPDATE_NETWORK_STATE, state, info);
48962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
49062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
49162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleUpdateNetworkState(int state, NetworkInfo info) {
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNetworkAvailable = (state == LocationProvider.AVAILABLE);
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
494f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) {
49503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            Log.d(TAG, "updateNetworkState " + (mNetworkAvailable ? "available" : "unavailable")
49603d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                + " info: " + info);
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
49803d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood
49950130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood        if (info != null) {
500a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            boolean dataEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
501a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                                                         Settings.Secure.MOBILE_DATA, 1) == 1;
502a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            boolean networkAvailable = info.isAvailable() && dataEnabled;
503a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            String defaultApn = getSelectedApn();
504a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            if (defaultApn == null) {
505a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                defaultApn = "dummy-apn";
506a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            }
507a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang
50850130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood            native_update_network_state(info.isConnected(), info.getType(),
509a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                                        info.isRoaming(), networkAvailable,
510a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                                        info.getExtraInfo(), defaultApn);
51150130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood        }
51250130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood
51303d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood        if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL
51403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
51503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            String apnName = info.getExtraInfo();
51683b69713f2dbeee7ff5e07836673a9a477be236fStephen Li            if (mNetworkAvailable) {
51783b69713f2dbeee7ff5e07836673a9a477be236fStephen Li                if (apnName == null) {
51883b69713f2dbeee7ff5e07836673a9a477be236fStephen Li                    /* Assign a dummy value in the case of C2K as otherwise we will have a runtime
51983b69713f2dbeee7ff5e07836673a9a477be236fStephen Li                    exception in the following call to native_agps_data_conn_open*/
52083b69713f2dbeee7ff5e07836673a9a477be236fStephen Li                    apnName = "dummy-apn";
52183b69713f2dbeee7ff5e07836673a9a477be236fStephen Li                }
52203d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsApn = apnName;
5238efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                if (DEBUG) Log.d(TAG, "mAGpsDataConnectionIpAddr " + mAGpsDataConnectionIpAddr);
5248efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                if (mAGpsDataConnectionIpAddr != 0xffffffff) {
5258efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                    boolean route_result;
5268efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                    if (DEBUG) Log.d(TAG, "call requestRouteToHost");
5278efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                    route_result = mConnMgr.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_SUPL,
5288efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                        mAGpsDataConnectionIpAddr);
5298efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                    if (route_result == false) Log.d(TAG, "call requestRouteToHost failed");
5308efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                }
53103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                if (DEBUG) Log.d(TAG, "call native_agps_data_conn_open");
53203d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                native_agps_data_conn_open(apnName);
53303d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
53403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            } else {
53503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                if (DEBUG) Log.d(TAG, "call native_agps_data_conn_failed");
53603d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsApn = null;
53703d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
53803d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                native_agps_data_conn_failed();
53903d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            }
54003d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood        }
54103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood
54262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (mNetworkAvailable) {
54362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (mInjectNtpTimePending) {
54498e48691f738680fe59e7383a41458e7337daccdMike Lockwood                sendMessage(INJECT_NTP_TIME, 0, null);
54562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            }
54662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (mDownloadXtraDataPending) {
54798e48691f738680fe59e7383a41458e7337daccdMike Lockwood                sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
54862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            }
54962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
55062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
55162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
55262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleInjectNtpTime() {
55362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (!mNetworkAvailable) {
55462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            // try again when network is up
55562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mInjectNtpTimePending = true;
55662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            return;
55762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
55862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mInjectNtpTimePending = false;
55962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
56062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        long delay;
56162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
562104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey        // force refresh NTP cache when outdated
563104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey        if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
564104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey            mNtpTime.forceRefresh();
565104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey        }
566104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey
567104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey        // only update when NTP time is fresh
568104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey        if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
569104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey            long time = mNtpTime.getCachedNtpTime();
570104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey            long timeReference = mNtpTime.getCachedNtpTimeReference();
571104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey            long certainty = mNtpTime.getCacheCertainty();
57262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            long now = System.currentTimeMillis();
57362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
57462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            Log.d(TAG, "NTP server returned: "
57562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    + time + " (" + new Date(time)
57662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    + ") reference: " + timeReference
57762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    + " certainty: " + certainty
5781879d284bf3dd704dbc8c95aad262ebbe3c3c0a4Mike Lockwood                    + " system time offset: " + (time - now));
57962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
580104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey            native_inject_time(time, timeReference, (int) certainty);
58162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            delay = NTP_INTERVAL;
58262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        } else {
58362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (DEBUG) Log.d(TAG, "requestTime failed");
58462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            delay = RETRY_INTERVAL;
58562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
58662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
5879b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood        if (mPeriodicTimeInjection) {
5889b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            // send delayed message for next NTP injection
5899b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            // since this is delayed and not urgent we do not hold a wake lock here
5909b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            mHandler.removeMessages(INJECT_NTP_TIME);
5919b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            mHandler.sendMessageDelayed(Message.obtain(mHandler, INJECT_NTP_TIME), delay);
5929b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood        }
59362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
59462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
59562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleDownloadXtraData() {
5965723dfe8c87d0887b8926f43637ed300466890d2Mike Lockwood        if (!mNetworkAvailable) {
59762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            // try again when network is up
59862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mDownloadXtraDataPending = true;
59962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            return;
60062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
60162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mDownloadXtraDataPending = false;
60262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
60362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
60462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
60562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        byte[] data = xtraDownloader.downloadXtraData();
60662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (data != null) {
60762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (DEBUG) {
60862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                Log.d(TAG, "calling native_inject_xtra_data");
60962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            }
61062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            native_inject_xtra_data(data, data.length);
61162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        } else {
61262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            // try again later
61398e48691f738680fe59e7383a41458e7337daccdMike Lockwood            // since this is delayed and not urgent we do not hold a wake lock here
61462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mHandler.removeMessages(DOWNLOAD_XTRA_DATA);
61562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mHandler.sendMessageDelayed(Message.obtain(mHandler, DOWNLOAD_XTRA_DATA), RETRY_INTERVAL);
61662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
620fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     * This is called to inform us when another location provider returns a location.
621fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     * Someday we might use this for network location injection to aid the GPS
622fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     */
623fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    public void updateLocation(Location location) {
62498e48691f738680fe59e7383a41458e7337daccdMike Lockwood        sendMessage(UPDATE_LOCATION, 0, location);
62562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
62662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
62762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleUpdateLocation(Location location) {
628d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        if (location.hasAccuracy()) {
629d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood            native_inject_location(location.getLatitude(), location.getLongitude(),
630d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood                    location.getAccuracy());
631d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        }
632fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    }
633fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood
634fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    /**
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to a
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * satellite-based positioning system (e.g., GPS), false
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise.
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresSatellite() {
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to an appropriate
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * cellular network (e.g., to make use of cell tower IDs), false
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise.
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresCell() {
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the use of this provider may result in a
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * monetary charge to the user, false if use is free.  It is up to
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * each provider to give accurate information.
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasMonetaryCost() {
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide altitude
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports altitude
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsAltitude() {
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide speed
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports speed
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsSpeed() {
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide bearing
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports bearing
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsBearing() {
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the power requirement for this provider.
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the power requirement for this provider, as one of the
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * constants Criteria.POWER_REQUIREMENT_*.
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getPowerRequirement() {
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Criteria.POWER_HIGH;
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
70203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood     * Returns true if this provider meets the given criteria,
70303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood     * false otherwise.
70403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood     */
70503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public boolean meetsCriteria(Criteria criteria) {
70603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        return (criteria.getPowerRequirement() != Criteria.POWER_LOW);
70703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
70803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
70903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    /**
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the horizontal accuracy of this provider
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the accuracy of location from this provider, as one
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of the constants Criteria.ACCURACY_*.
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getAccuracy() {
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Criteria.ACCURACY_FINE;
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Enables this provider.  When enabled, calls to getStatus()
7214e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * must be handled.  Hardware may be started up
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the provider is enabled.
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
72462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    public void enable() {
72562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        synchronized (mHandler) {
72698e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(ENABLE, 1, null);
72762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
72862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
72962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
73062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleEnable() {
73162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (DEBUG) Log.d(TAG, "handleEnable");
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabled) return;
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnabled = native_init();
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabled) {
7361a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood            mSupportsXtra = native_supports_xtra();
737734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mSuplServerHost != null) {
738734d6031a662a275ec68627bd1258159041d44deMike Lockwood                native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
739734d6031a662a275ec68627bd1258159041d44deMike Lockwood            }
740734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mC2KServerHost != null) {
741734d6031a662a275ec68627bd1258159041d44deMike Lockwood                native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
742734d6031a662a275ec68627bd1258159041d44deMike Lockwood            }
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Failed to enable location provider");
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Disables this provider.  When disabled, calls to getStatus()
7504e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * need not be handled.  Hardware may be shut
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * down while the provider is disabled.
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
75362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    public void disable() {
75462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        synchronized (mHandler) {
75598e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(ENABLE, 0, null);
75662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
75762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
75862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
75962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleDisable() {
76089096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        if (DEBUG) Log.d(TAG, "handleDisable");
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mEnabled) return;
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnabled = false;
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        stopNavigating();
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
766cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood        // do this before releasing wakelock
767cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood        native_cleanup();
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
770d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    public boolean isEnabled() {
771d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        return mEnabled;
772d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    }
773d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getStatus(Bundle extras) {
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras != null) {
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            extras.putInt("satellites", mSvCount);
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatus;
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateStatus(int status, int svCount) {
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (status != mStatus || svCount != mSvCount) {
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatus = status;
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSvCount = svCount;
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationExtras.putInt("satellites", svCount);
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatusUpdateTime = SystemClock.elapsedRealtime();
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public long getStatusUpdateTime() {
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatusUpdateTime;
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void enableLocationTracking(boolean enable) {
79503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        // FIXME - should set a flag here to avoid race conditions with single shot request
79662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        synchronized (mHandler) {
79798e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(ENABLE_TRACKING, (enable ? 1 : 0), null);
79862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
79962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
80062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
80162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleEnableLocationTracking(boolean enable) {
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (enable) {
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = 0;
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
80503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            startNavigating(false);
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
80704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
80804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                mAlarmManager.cancel(mWakeupIntent);
80904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                mAlarmManager.cancel(mTimeoutIntent);
81004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            }
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stopNavigating();
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
81503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public boolean requestSingleShotFix() {
81603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        if (mStarted) {
81703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            // cannot do single shot if already navigating
81803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            return false;
81903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
82003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        synchronized (mHandler) {
82103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mHandler.removeMessages(REQUEST_SINGLE_SHOT);
82203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            Message m = Message.obtain(mHandler, REQUEST_SINGLE_SHOT);
82303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mHandler.sendMessage(m);
82403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
82503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        return true;
82603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
82703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
82803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private void handleRequestSingleShot() {
82903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        mTTFF = 0;
83003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        mLastFixTime = 0;
83103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        startNavigating(true);
83203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
83303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
8347e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn    public void setMinTime(long minTime, WorkSource ws) {
835f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) Log.d(TAG, "setMinTime " + minTime);
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (minTime >= 0) {
83804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            mFixInterval = (int)minTime;
83904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
84004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
84104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
84204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                        mFixInterval, 0, 0)) {
84304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                    Log.e(TAG, "set_position_mode failed in setMinTime()");
84404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                }
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8493c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    public String getInternalState() {
850b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly        StringBuilder s = new StringBuilder();
851b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly        s.append("  mFixInterval=").append(mFixInterval).append("\n");
852b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly        s.append("  mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities)).append(" (");
853b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly        if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHED ");
854b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly        if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
855b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly        if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA ");
856b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly        if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT ");
857b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly        if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME ");
858b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly        s.append(")\n");
859b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly
860b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly        s.append(native_get_internal_state());
861b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly        return s.toString();
8623c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    }
8633c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final class Listener implements IBinder.DeathRecipient {
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IGpsStatusListener mListener;
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int mSensors = 0;
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Listener(IGpsStatusListener listener) {
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = listener;
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
874f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato            if (DEBUG) Log.d(TAG, "GPS status listener died");
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(mListeners) {
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mListeners.remove(this);
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
879fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu            if (mListener != null) {
880fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu                mListener.asBinder().unlinkToDeath(this, 0);
881fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu            }
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8852f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    public void addListener(int uid) {
88698e48691f738680fe59e7383a41458e7337daccdMike Lockwood        synchronized (mWakeLock) {
88798e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mPendingListenerMessages++;
8887e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            mWakeLock.acquire();
88998e48691f738680fe59e7383a41458e7337daccdMike Lockwood            Message m = Message.obtain(mHandler, ADD_LISTENER);
89098e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.arg1 = uid;
89198e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.sendMessage(m);
89298e48691f738680fe59e7383a41458e7337daccdMike Lockwood        }
89362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
89462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
89562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleAddListener(int uid) {
8962e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
8972e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mClientUids.indexOfKey(uid) >= 0) {
8982e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                // Shouldn't be here -- already have this uid.
8992e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                Log.w(TAG, "Duplicate add listener for uid " + uid);
9002e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                return;
9012e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            }
9022e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            mClientUids.put(uid, 0);
9032e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mNavigating) {
9042e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
9052e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    mBatteryStats.noteStartGps(uid);
9062e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
9072e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in addListener");
9082e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                }
9092f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
9102f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
9112f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
9122f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
9132f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    public void removeListener(int uid) {
91498e48691f738680fe59e7383a41458e7337daccdMike Lockwood        synchronized (mWakeLock) {
91598e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mPendingListenerMessages++;
91698e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mWakeLock.acquire();
91798e48691f738680fe59e7383a41458e7337daccdMike Lockwood            Message m = Message.obtain(mHandler, REMOVE_LISTENER);
91898e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.arg1 = uid;
91998e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.sendMessage(m);
92098e48691f738680fe59e7383a41458e7337daccdMike Lockwood        }
92162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
92262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
92362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleRemoveListener(int uid) {
9242e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
9252e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mClientUids.indexOfKey(uid) < 0) {
9262e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                // Shouldn't be here -- don't have this uid.
9272e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                Log.w(TAG, "Unneeded remove listener for uid " + uid);
9282e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                return;
9292e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            }
9302e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            mClientUids.delete(uid);
9312e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mNavigating) {
9322e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
9332e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    mBatteryStats.noteStopGps(uid);
9342e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
9352e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in removeListener");
9362e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                }
9372f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
9382f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
9392f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
9402f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendExtraCommand(String command, Bundle extras) {
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
94363aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        long identity = Binder.clearCallingIdentity();
94463aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        boolean result = false;
94563aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ("delete_aiding_data".equals(command)) {
94763aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood            result = deleteAidingData(extras);
94863aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        } else if ("force_time_injection".equals(command)) {
94998e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(INJECT_NTP_TIME, 0, null);
95063aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood            result = true;
95163aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        } else if ("force_xtra_injection".equals(command)) {
9521a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood            if (mSupportsXtra) {
95393bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                xtraDownloadRequest();
95463aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood                result = true;
95593bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            }
95663aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        } else {
95763aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood            Log.w(TAG, "sendExtraCommand: unknown command " + command);
95893bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
96063aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        Binder.restoreCallingIdentity(identity);
96163aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        return result;
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean deleteAidingData(Bundle extras) {
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags;
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras == null) {
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = GPS_DELETE_ALL;
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = 0;
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (flags != 0) {
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_delete_aiding_data(flags);
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
99403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private void startNavigating(boolean singleShot) {
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStarted) {
99629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (DEBUG) Log.d(TAG, "startNavigating");
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = true;
99803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mSingleShot = singleShot;
99903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mPositionMode = GPS_POSITION_MODE_STANDALONE;
100003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
100103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood             if (Settings.Secure.getInt(mContext.getContentResolver(),
1002660bbfcc54d48d5d32e64da683c76b9c372c19b1Mike Lockwood                    Settings.Secure.ASSISTED_GPS_ENABLED, 1) != 0) {
100303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                if (singleShot && hasCapability(GPS_CAPABILITY_MSA)) {
100403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    mPositionMode = GPS_POSITION_MODE_MS_ASSISTED;
10058dc16c27e23dae5bdf65fd2a2ced97c2f645a633Mike Lockwood                } else if (hasCapability(GPS_CAPABILITY_MSB)) {
100603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    mPositionMode = GPS_POSITION_MODE_MS_BASED;
100703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                }
1008bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood            }
1009bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood
101004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
101104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
101204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                    interval, 0, 0)) {
101304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                mStarted = false;
101404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                Log.e(TAG, "set_position_mode failed in startNavigating()");
101504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                return;
101604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            }
101704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!native_start()) {
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStarted = false;
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.e(TAG, "native_start failed in startNavigating()");
10200632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                return;
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
102415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
102529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            mFixRequestTime = System.currentTimeMillis();
102604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
102704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
102804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                // and our fix interval is not short
102904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                if (mFixInterval >= NO_FIX_TIMEOUT) {
103004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                    mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
103104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                            SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
103204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                }
10330632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            }
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
103762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void stopNavigating() {
103829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (DEBUG) Log.d(TAG, "stopNavigating");
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mStarted) {
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = false;
104103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mSingleShot = false;
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_stop();
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = 0;
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = LOCATION_INVALID;
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
104815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10520632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private void hibernate() {
10530632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        // stop GPS until our next fix interval arrives
10540632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        stopNavigating();
10550632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mTimeoutIntent);
10560632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mWakeupIntent);
10570632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        long now = SystemClock.elapsedRealtime();
10580632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
105904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                SystemClock.elapsedRealtime() + mFixInterval, mWakeupIntent);
106004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    }
106104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
106204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private boolean hasCapability(int capability) {
106304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood        return ((mEngineCapabilities & capability) != 0);
10640632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    }
10650632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our position.
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportLocation(int flags, double latitude, double longitude, double altitude,
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float speed, float bearing, float accuracy, long timestamp) {
107129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                " timestamp: " + timestamp);
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mLocation) {
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = flags;
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLatitude(latitude);
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLongitude(longitude);
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setTime(timestamp);
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAltitude(altitude);
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAltitude();
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setSpeed(speed);
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeSpeed();
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setBearing(bearing);
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeBearing();
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAccuracy(accuracy);
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAccuracy();
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1101ced2b2c09a209e017f02cf28ddd9d35b2d8b8adaSean Barbeau            mLocation.setExtras(mLocationExtras);
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
110315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            try {
1104a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                mLocationManager.reportLocation(mLocation, false);
110515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            } catch (RemoteException e) {
110615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Log.e(TAG, "RemoteException calling reportLocation");
110715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1110fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        mLastFixTime = System.currentTimeMillis();
1111fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        // report time to first fix
1112fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        if (mTTFF == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1113fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            mTTFF = (int)(mLastFixTime - mFixRequestTime);
1114f4dffd8a45386b5a5f0e6de4f30facc9eaac4001The Android Open Source Project            if (DEBUG) Log.d(TAG, "TTFF: " + mTTFF);
1115fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson
1116fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            // notify status listeners
1117fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            synchronized(mListeners) {
1118fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                int size = mListeners.size();
1119fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                for (int i = 0; i < size; i++) {
1120fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    Listener listener = mListeners.get(i);
1121fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    try {
1122f4dffd8a45386b5a5f0e6de4f30facc9eaac4001The Android Open Source Project                        listener.mListener.onFirstFix(mTTFF);
1123fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    } catch (RemoteException e) {
1124fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        Log.w(TAG, "RemoteException in stopNavigating");
1125fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        mListeners.remove(listener);
1126fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        // adjust for size of list changing
1127fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        size--;
1128fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    }
1129fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                }
1130fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            }
1131fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        }
1132fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson
113303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        if (mSingleShot) {
113403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            stopNavigating();
113503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
113615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mStarted && mStatus != LocationProvider.AVAILABLE) {
1137d53ba017ee2381383b4bb4d92e6e0e661431660fMike Lockwood            // we want to time out if we do not receive a fix
1138b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood            // within the time out and we are requesting infrequent fixes
113904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {
1140b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood                mAlarmManager.cancel(mTimeoutIntent);
1141b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood            }
1142b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is receiving fixes.
114400b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
114500b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
114715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.AVAILABLE, mSvCount);
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
114929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
1150b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly       if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted &&
1151b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly               mFixInterval > GPS_POLLING_THRESHOLD_INTERVAL) {
1152d53ba017ee2381383b4bb4d92e6e0e661431660fMike Lockwood            if (DEBUG) Log.d(TAG, "got fix, hibernating");
11530632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            hibernate();
115429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        }
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   }
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our status
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportStatus(int status) {
1161b8d9033d9928209e68518c4b12fea74187ddb382Mike Lockwood        if (DEBUG) Log.v(TAG, "reportStatus status: " + status);
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11632e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
11642e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            boolean wasNavigating = mNavigating;
1165dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood
1166cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            switch (status) {
1167cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_SESSION_BEGIN:
1168cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mNavigating = true;
1169271f9f172b241607b1ed39a7709c3ed47ee5dee7Mike Lockwood                    mEngineOn = true;
1170cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1171cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_SESSION_END:
1172cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mNavigating = false;
1173cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1174cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_ENGINE_ON:
1175cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mEngineOn = true;
1176cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1177cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_ENGINE_OFF:
1178cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mEngineOn = false;
1179271f9f172b241607b1ed39a7709c3ed47ee5dee7Mike Lockwood                    mNavigating = false;
1180cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1181cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            }
1182cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood
1183dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood            if (wasNavigating != mNavigating) {
1184dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                int size = mListeners.size();
1185dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                for (int i = 0; i < size; i++) {
1186dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    Listener listener = mListeners.get(i);
1187dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    try {
1188dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        if (mNavigating) {
1189dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            listener.mListener.onGpsStarted();
1190dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        } else {
1191dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            listener.mListener.onGpsStopped();
1192dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        }
1193dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    } catch (RemoteException e) {
1194dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        Log.w(TAG, "RemoteException in reportStatus");
1195dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        mListeners.remove(listener);
1196dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        // adjust for size of list changing
1197dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        size--;
1198dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    }
1199dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                }
1200dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood
12012e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
1202dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    // update battery stats
1203dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    for (int i=mClientUids.size() - 1; i >= 0; i--) {
1204dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        int uid = mClientUids.keyAt(i);
1205dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        if (mNavigating) {
1206dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            mBatteryStats.noteStartGps(uid);
1207dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        } else {
1208dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            mBatteryStats.noteStopGps(uid);
1209dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        }
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12112e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
12122e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in reportStatus");
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1215dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                // send an intent to notify that the GPS has been enabled or disabled.
121600b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood                Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
121700b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood                intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
1218dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                mContext.sendBroadcast(intent);
12192f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update SV info
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportSvStatus() {
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(mListeners) {
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int size = mListeners.size();
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < size; i++) {
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Listener listener = mListeners.get(i);
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs,
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSvElevations, mSvAzimuths, mSvMasks[EPHEMERIS_MASK],
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK]);
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.w(TAG, "RemoteException in reportSvInfo");
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mListeners.remove(listener);
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // adjust for size of list changing
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    size--;
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
124729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) {
124829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            Log.v(TAG, "SV count: " + svCount +
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) +
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK]));
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < svCount; i++) {
125229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                Log.v(TAG, "sv: " + mSvs[i] +
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " snr: " + (float)mSnrs[i]/10 +
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " elev: " + mSvElevations[i] +
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " azimuth: " + mSvAzimuths[i] +
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " E") +
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " A") +
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U"));
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12620881f4f9339febee85c9ab4cba69970ac5cbde55Kevin.KY Tsai        // return number of sets used in fix instead of total
12630881f4f9339febee85c9ab4cba69970ac5cbde55Kevin.KY Tsai        updateStatus(mStatus, Integer.bitCount(mSvMasks[USED_FOR_FIX_MASK]));
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
126515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
126604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is no longer receiving fixes.
126800b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
126900b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
127115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
127458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
127558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    /**
1276e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood     * called from native code to update AGPS status
127758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood     */
12788efd74dbedb65f69734318d9d6be70767f30b57aStephen Li    private void reportAGpsStatus(int type, int status, int ipaddr) {
127958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        switch (status) {
1280e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_REQUEST_AGPS_DATA_CONN:
1281b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
12822acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                // Set mAGpsDataConnectionState before calling startUsingNetworkFeature
12832acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                //  to avoid a race condition with handleUpdateNetworkState()
12842acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
12852acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                int result = mConnMgr.startUsingNetworkFeature(
128658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                        ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
12878efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                mAGpsDataConnectionIpAddr = ipaddr;
128858bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                if (result == Phone.APN_ALREADY_ACTIVE) {
12892d4d1bf14b531de9d4238b1e41b53c77f8976405Mike Lockwood                    if (DEBUG) Log.d(TAG, "Phone.APN_ALREADY_ACTIVE");
1290b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    if (mAGpsApn != null) {
12918efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                        Log.d(TAG, "mAGpsDataConnectionIpAddr " + mAGpsDataConnectionIpAddr);
12928efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                        if (mAGpsDataConnectionIpAddr != 0xffffffff) {
12938efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                            boolean route_result;
12948efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                            if (DEBUG) Log.d(TAG, "call requestRouteToHost");
12958efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                            route_result = mConnMgr.requestRouteToHost(
12968efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                                ConnectivityManager.TYPE_MOBILE_SUPL,
12978efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                                mAGpsDataConnectionIpAddr);
12988efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                            if (route_result == false) Log.d(TAG, "call requestRouteToHost failed");
12998efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                        }
1300b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        native_agps_data_conn_open(mAGpsApn);
1301b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
1302b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    } else {
1303b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        Log.e(TAG, "mAGpsApn not set when receiving Phone.APN_ALREADY_ACTIVE");
13042acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
1305b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        native_agps_data_conn_failed();
1306b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    }
130758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else if (result == Phone.APN_REQUEST_STARTED) {
13084a7b65e0d544ef1feff8e1e5789f469f89ebb85cMike Lockwood                    if (DEBUG) Log.d(TAG, "Phone.APN_REQUEST_STARTED");
13092acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                    // Nothing to do here
131058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else {
1311b8d9033d9928209e68518c4b12fea74187ddb382Mike Lockwood                    if (DEBUG) Log.d(TAG, "startUsingNetworkFeature failed");
13122acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
1313e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_failed();
131458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
131558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1316e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_RELEASE_AGPS_DATA_CONN:
1317b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
1318e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
131958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                    mConnMgr.stopUsingNetworkFeature(
132058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                            ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
1321e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_closed();
1322e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
132358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
132458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1325e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONNECTED:
1326b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
132758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1328e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_DONE:
1329b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
133058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1331e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_FAILED:
1332b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
133358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
133458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        }
133558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    }
133658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1337b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    /**
1338b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood     * called from native code to report NMEA data received
1339b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood     */
1340f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood    private void reportNmea(long timestamp) {
1341b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood        synchronized(mListeners) {
1342b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            int size = mListeners.size();
1343b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            if (size > 0) {
1344b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                // don't bother creating the String if we have no listeners
1345f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood                int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
1346b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                String nmea = new String(mNmeaBuffer, 0, length);
1347b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood
1348b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                for (int i = 0; i < size; i++) {
1349b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    Listener listener = mListeners.get(i);
1350b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    try {
1351b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        listener.mListener.onNmeaReceived(timestamp, nmea);
1352b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    } catch (RemoteException e) {
1353b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        Log.w(TAG, "RemoteException in reportNmea");
1354b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        mListeners.remove(listener);
1355b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        // adjust for size of list changing
1356b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        size--;
1357b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    }
1358b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                }
1359b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            }
1360b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood        }
1361b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    }
1362b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood
136362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    /**
136404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood     * called from native code to inform us what the GPS engine capabilities are
136504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood     */
136604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private void setEngineCapabilities(int capabilities) {
136704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood        mEngineCapabilities = capabilities;
13689b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood
13699b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood        if (!hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME) && !mPeriodicTimeInjection) {
13709b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            mPeriodicTimeInjection = true;
13719b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            requestUtcTime();
13729b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood        }
137304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    }
137404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
137504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    /**
137662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood     * called from native code to request XTRA data
137762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood     */
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void xtraDownloadRequest() {
1379f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
138098e48691f738680fe59e7383a41458e7337daccdMike Lockwood        sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
138322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    //=============================================================
138422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // NI Client support
13851e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    //=============================================================
138622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
13871e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        // Sends a response for an NI reqeust to HAL.
13881e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        public boolean sendNiResponse(int notificationId, int userResponse)
13891e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        {
13901e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            // TODO Add Permission check
13911e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13921e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            StringBuilder extrasBuf = new StringBuilder();
13931e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13941e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
13951e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                    ", response: " + userResponse);
13961e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            native_send_ni_response(notificationId, userResponse);
13971e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            return true;
13981e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
139922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    };
140022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
140122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    public INetInitiatedListener getNetInitiatedListener() {
140222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        return mNetInitiatedListener;
140322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    }
140422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
140522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // Called by JNI function to report an NI request.
14061e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    public void reportNiNotification(
14071e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int notificationId,
14081e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int niType,
14091e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int notifyFlags,
14101e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int timeout,
14111e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int defaultResponse,
14121e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String requestorId,
14131e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String text,
14141e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int requestorIdEncoding,
14151e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int textEncoding,
14161e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String extras  // Encoded extra data
141722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        )
14181e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    {
14191e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Log.i(TAG, "reportNiNotification: entered");
14201e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Log.i(TAG, "notificationId: " + notificationId +
14211e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", niType: " + niType +
14221e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", notifyFlags: " + notifyFlags +
14231e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", timeout: " + timeout +
14241e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", defaultResponse: " + defaultResponse);
14251e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14261e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Log.i(TAG, "requestorId: " + requestorId +
14271e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", text: " + text +
14281e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", requestorIdEncoding: " + requestorIdEncoding +
14291e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", textEncoding: " + textEncoding);
14301e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14311e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        GpsNiNotification notification = new GpsNiNotification();
14321e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14331e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.notificationId = notificationId;
14341e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.niType = niType;
14351e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
14361e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
14371e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
14381e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.timeout = timeout;
14391e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.defaultResponse = defaultResponse;
14401e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.requestorId = requestorId;
14411e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.text = text;
14421e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.requestorIdEncoding = requestorIdEncoding;
14431e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.textEncoding = textEncoding;
14441e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14451e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        // Process extras, assuming the format is
14461e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        // one of more lines of "key = value"
14471e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Bundle bundle = new Bundle();
14481e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14491e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        if (extras == null) extras = "";
14501e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Properties extraProp = new Properties();
14511e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14521e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        try {
1453104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey            extraProp.load(new StringReader(extras));
14541e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
14551e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        catch (IOException e)
14561e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        {
14571e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
14581e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
14591e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14601e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        for (Entry<Object, Object> ent : extraProp.entrySet())
14611e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        {
14621e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            bundle.putString((String) ent.getKey(), (String) ent.getValue());
14631e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
14641e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14651e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.extras = bundle;
14661e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14671e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        mNIHandler.handleNiNotification(notification);
14681e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
14691e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14701e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    /**
14711e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * Called from native code to request set id info.
14721e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * We should be careful about receiving null string from the TelephonyManager,
14731e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * because sending null String to JNI function would cause a crash.
14741e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     */
14751e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14761e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void requestSetID(int flags) {
14771e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        TelephonyManager phone = (TelephonyManager)
14781e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                mContext.getSystemService(Context.TELEPHONY_SERVICE);
14791e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        int    type = AGPS_SETID_TYPE_NONE;
14801e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        String data = "";
14811e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14821e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
14831e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String data_temp = phone.getSubscriberId();
14841e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            if (data_temp == null) {
14851e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework does not have the SIM card ready.
14861e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else {
14871e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework has the SIM card.
14881e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                data = data_temp;
14891e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                type = AGPS_SETID_TYPE_IMSI;
14901e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            }
14911e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
14921e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
14931e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String data_temp = phone.getLine1Number();
14941e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            if (data_temp == null) {
14951e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework does not have the SIM card ready.
14961e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else {
14971e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework has the SIM card.
14981e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                data = data_temp;
14991e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                type = AGPS_SETID_TYPE_MSISDN;
15001e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            }
15011e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
15021e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        native_agps_set_id(type, data);
15031e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
15041e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
15051e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    /**
15069b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood     * Called from native code to request utc time info
15079b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood     */
15089b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood
15099b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    private void requestUtcTime() {
15109b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood        sendMessage(INJECT_NTP_TIME, 0, null);
15119b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    }
15129b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood
15139b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    /**
15141e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * Called from native code to request reference location info
15151e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     */
15161e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
15171e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void requestRefLocation(int flags) {
15181e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        TelephonyManager phone = (TelephonyManager)
15191e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                mContext.getSystemService(Context.TELEPHONY_SERVICE);
15201e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        if (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
15211e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation();
1522edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood            if ((gsm_cell != null) && (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) &&
1523edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                    (phone.getNetworkOperator() != null) &&
1524edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                        (phone.getNetworkOperator().length() > 3)) {
15251e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                int type;
15261e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0,3));
15271e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3));
1528edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                int networkType = phone.getNetworkType();
1529edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                if (networkType == TelephonyManager.NETWORK_TYPE_UMTS
1530edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                    || networkType == TelephonyManager.NETWORK_TYPE_HSDPA
1531edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                    || networkType == TelephonyManager.NETWORK_TYPE_HSUPA
1532edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                    || networkType == TelephonyManager.NETWORK_TYPE_HSPA) {
15331e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                    type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
1534edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                } else {
15351e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                    type = AGPS_REF_LOCATION_TYPE_GSM_CELLID;
1536edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                }
15371e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                native_agps_set_ref_location_cellid(type, mcc, mnc,
15381e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                        gsm_cell.getLac(), gsm_cell.getCid());
1539edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood            } else {
15401e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                Log.e(TAG,"Error getting cell location info.");
1541edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood            }
15421e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
1543edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood        else {
15441e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            Log.e(TAG,"CDMA not supported.");
1545edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood        }
15461e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
154722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
154898e48691f738680fe59e7383a41458e7337daccdMike Lockwood    private void sendMessage(int message, int arg, Object obj) {
154998e48691f738680fe59e7383a41458e7337daccdMike Lockwood        // hold a wake lock while messages are pending
155098e48691f738680fe59e7383a41458e7337daccdMike Lockwood        synchronized (mWakeLock) {
155198e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mPendingMessageBits |= (1 << message);
155298e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mWakeLock.acquire();
155398e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.removeMessages(message);
155498e48691f738680fe59e7383a41458e7337daccdMike Lockwood            Message m = Message.obtain(mHandler, message);
155598e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.arg1 = arg;
155698e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.obj = obj;
155798e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.sendMessage(m);
155898e48691f738680fe59e7383a41458e7337daccdMike Lockwood        }
155998e48691f738680fe59e7383a41458e7337daccdMike Lockwood    }
156098e48691f738680fe59e7383a41458e7337daccdMike Lockwood
156162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private final class ProviderHandler extends Handler {
156262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        @Override
15634a7b65e0d544ef1feff8e1e5789f469f89ebb85cMike Lockwood        public void handleMessage(Message msg) {
156498e48691f738680fe59e7383a41458e7337daccdMike Lockwood            int message = msg.what;
156598e48691f738680fe59e7383a41458e7337daccdMike Lockwood            switch (message) {
156662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case ENABLE:
156762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    if (msg.arg1 == 1) {
156862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                        handleEnable();
156962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    } else {
157062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                        handleDisable();
15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
157262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
157362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case ENABLE_TRACKING:
157462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleEnableLocationTracking(msg.arg1 == 1);
157562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
157603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                case REQUEST_SINGLE_SHOT:
157703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    handleRequestSingleShot();
157803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    break;
157962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case UPDATE_NETWORK_STATE:
158062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleUpdateNetworkState(msg.arg1, (NetworkInfo)msg.obj);
158162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
158262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case INJECT_NTP_TIME:
158362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleInjectNtpTime();
158462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
158562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case DOWNLOAD_XTRA_DATA:
15861a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood                    if (mSupportsXtra) {
158762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                        handleDownloadXtraData();
15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
158962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
159062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case UPDATE_LOCATION:
159162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleUpdateLocation((Location)msg.obj);
159262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
159362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case ADD_LISTENER:
159462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleAddListener(msg.arg1);
159562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
159662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case REMOVE_LISTENER:
159762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleRemoveListener(msg.arg1);
159862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
15999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
160098e48691f738680fe59e7383a41458e7337daccdMike Lockwood            // release wake lock if no messages are pending
160198e48691f738680fe59e7383a41458e7337daccdMike Lockwood            synchronized (mWakeLock) {
160298e48691f738680fe59e7383a41458e7337daccdMike Lockwood                mPendingMessageBits &= ~(1 << message);
160398e48691f738680fe59e7383a41458e7337daccdMike Lockwood                if (message == ADD_LISTENER || message == REMOVE_LISTENER) {
160498e48691f738680fe59e7383a41458e7337daccdMike Lockwood                    mPendingListenerMessages--;
160598e48691f738680fe59e7383a41458e7337daccdMike Lockwood                }
160698e48691f738680fe59e7383a41458e7337daccdMike Lockwood                if (mPendingMessageBits == 0 && mPendingListenerMessages == 0) {
160798e48691f738680fe59e7383a41458e7337daccdMike Lockwood                    mWakeLock.release();
160898e48691f738680fe59e7383a41458e7337daccdMike Lockwood                }
160998e48691f738680fe59e7383a41458e7337daccdMike Lockwood            }
16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
161162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    };
16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
161389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private final class GpsLocationProviderThread extends Thread {
161489096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood
161589096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        public GpsLocationProviderThread() {
161689096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            super("GpsLocationProvider");
161789096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        }
161889096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood
161989096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        public void run() {
162089096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
162189096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            initialize();
162289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            Looper.prepare();
162389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            mHandler = new ProviderHandler();
162489096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            // signal when we are initialized and ready to go
162589096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            mInitializedLatch.countDown();
162689096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            Looper.loop();
162789096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        }
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1630a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang    private String getSelectedApn() {
1631a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang        Uri uri = Uri.parse("content://telephony/carriers/preferapn");
1632a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang        String apn = null;
1633a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang
1634a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang        Cursor cursor = mContext.getContentResolver().query(uri, new String[] {"apn"},
1635a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                null, null, Carriers.DEFAULT_SORT_ORDER);
1636a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang
1637a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang        if (null != cursor) {
1638a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            try {
1639a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                if (cursor.moveToFirst()) {
1640a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                    apn = cursor.getString(0);
1641a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                }
1642a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            } finally {
1643a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                cursor.close();
1644a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            }
1645a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang        }
1646a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang        return apn;
1647a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang    }
1648a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang
16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for GPS SV statistics
16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int MAX_SVS = 32;
16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int EPHEMERIS_MASK = 0;
16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int ALMANAC_MASK = 1;
16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int USED_FOR_FIX_MASK = 2;
16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // preallocated arrays, to avoid memory allocation in reportStatus()
16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvs[] = new int[MAX_SVS];
16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSnrs[] = new float[MAX_SVS];
16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvElevations[] = new float[MAX_SVS];
16599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvAzimuths[] = new float[MAX_SVS];
16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvMasks[] = new int[3];
16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvCount;
1662b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    // preallocated to avoid memory allocation in reportNmea()
1663b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    private byte[] mNmeaBuffer = new byte[120];
16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static { class_init_native(); }
16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native void class_init_native();
16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native boolean native_is_supported();
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_init();
16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_cleanup();
167104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private native boolean native_set_position_mode(int mode, int recurrence, int min_interval,
167204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            int preferred_accuracy, int preferred_time);
167304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private native boolean native_start();
16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_stop();
16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_delete_aiding_data(int flags);
16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // returns number of SVs
16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // mask[0] is ephemeris mask and mask[1] is almanac mask
16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native int native_read_sv_status(int[] svs, float[] snrs,
16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] elevations, float[] azimuths, int[] masks);
1680f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood    private native int native_read_nmea(byte[] buffer, int bufferSize);
1681d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood    private native void native_inject_location(double latitude, double longitude, float accuracy);
1682d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood
16833c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    // XTRA Support
16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_time(long time, long timeReference, int uncertainty);
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_supports_xtra();
16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_xtra_data(byte[] data, int length);
1687105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
16883c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    // DEBUG Support
16893c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    private native String native_get_internal_state();
16903c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger
16913c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    // AGPS Support
1692e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_open(String apn);
1693e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_closed();
1694e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_failed();
16951e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private native void native_agps_ni_message(byte [] msg, int length);
1696a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood    private native void native_set_agps_server(int type, String hostname, int port);
169722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
169822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // Network-initiated (NI) Support
169922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private native void native_send_ni_response(int notificationId, int userResponse);
17001e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
17011e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // AGPS ril suport
17021e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
17031e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int lac, int cid);
17041e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private native void native_agps_set_id(int type, String setid);
170550130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood
170650130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood    private native void native_update_network_state(boolean connected, int type,
1707a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            boolean roaming, boolean available, String extraInfo, String defaultAPN);
17089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1709