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
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we are enabled
19689096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private volatile boolean mEnabled;
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we have network connectivity
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNetworkAvailable;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    // flags to trigger NTP or XTRA data download when network becomes available
20262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    // initialized to true so we do NTP and XTRA when the network comes up after booting
20362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private boolean mInjectNtpTimePending = true;
2045982bf66d4fdea38105d91ff0f9d38660ac87581Mike Lockwood    private boolean mDownloadXtraDataPending = true;
20562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
2069b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    // set to true if the GPS engine does not do on-demand NTP time requests
2079b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    private boolean mPeriodicTimeInjection;
2089b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if GPS is navigating
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNavigating;
211cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood
212cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood    // true if GPS engine is on
213cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood    private boolean mEngineOn;
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // requested frequency of fixes, in milliseconds
21604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private int mFixInterval = 1000;
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we started navigation
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mStarted;
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    // true if single shot request is in progress
22203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private boolean mSingleShot;
22303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
22404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // capabilities of the GPS engine
22504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private int mEngineCapabilities;
22604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
2271a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood    // true if XTRA is supported
2281a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood    private boolean mSupportsXtra;
2291a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for calculating time to first fix
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mFixRequestTime = 0;
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time to first fix for most recent session
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mTTFF = 0;
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time we received our last fix
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mLastFixTime;
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private int mPositionMode;
23804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // properties loaded from PROPERTIES_FILE
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Properties mProperties;
241734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private String mSuplServerHost;
242734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private int mSuplServerPort;
243734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private String mC2KServerHost;
244734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private int mC2KServerPort;
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final Context mContext;
247104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey    private final NtpTrustedTime mNtpTime;
24815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final ILocationManager mLocationManager;
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Bundle mLocationExtras = new Bundle();
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<Listener> mListeners = new ArrayList<Listener>();
25262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
25389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    // GpsLocationProvider's handler thread
25489096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private final Thread mThread;
25589096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    // Handler for processing events in mThread.
25662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private Handler mHandler;
25789096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    // Used to signal when our main thread has initialized everything
25889096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private final CountDownLatch mInitializedLatch = new CountDownLatch(1);
259105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
260e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private String mAGpsApn;
261e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private int mAGpsDataConnectionState;
2628efd74dbedb65f69734318d9d6be70767f30b57aStephen Li    private int mAGpsDataConnectionIpAddr;
2632f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final ConnectivityManager mConnMgr;
26422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private final GpsNetInitiatedHandler mNIHandler;
2652f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
2660528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    // Wakelocks
2670528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final static String WAKELOCK_KEY = "GpsLocationProvider";
2680528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final PowerManager.WakeLock mWakeLock;
26998e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // bitfield of pending messages to our Handler
27098e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // used only for messages that cannot have multiple instances queued
27198e48691f738680fe59e7383a41458e7337daccdMike Lockwood    private int mPendingMessageBits;
27298e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // separate counter for ADD_LISTENER and REMOVE_LISTENER messages,
27398e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // which might have multiple instances queued
27498e48691f738680fe59e7383a41458e7337daccdMike Lockwood    private int mPendingListenerMessages;
2750528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
27629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    // Alarms
27729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
2780632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
27929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final AlarmManager mAlarmManager;
28029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final PendingIntent mWakeupIntent;
2810632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final PendingIntent mTimeoutIntent;
28229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
2832f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final IBatteryStats mBatteryStats;
2842f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final SparseIntArray mClientUids = new SparseIntArray();
285105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // how often to request NTP time, in milliseconds
2874c126068527c9adba45aa227d40e245ee8e7c9a4Mike Lockwood    // current setting 24 hours
2884c126068527c9adba45aa227d40e245ee8e7c9a4Mike Lockwood    private static final long NTP_INTERVAL = 24*60*60*1000;
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // how long to wait if we have a network error in NTP or XTRA downloading
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current setting - 5 minutes
291f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood    private static final long RETRY_INTERVAL = 5*60*1000;
292f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood
29315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
29415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
29515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
29615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
29715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
29815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
29915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            synchronized(mListeners) {
30015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
30115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
30215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size; i++) {
30315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
30415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
30515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        // listener already added
30615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        return;
30715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
30815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
30915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
31015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = new Listener(listener);
31115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                binder.linkToDeath(l, 0);
31215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                mListeners.add(l);
31315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
31415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
31515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
31615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void removeGpsStatusListener(IGpsStatusListener listener) {
31715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
31815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
31915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
32015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
32115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            synchronized(mListeners) {
32215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
32315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = null;
32415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
32515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size && l == null; i++) {
32615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
32715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
32815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        l = test;
32915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
33015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
33115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
33215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                if (l != null) {
33315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    mListeners.remove(l);
33415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    binder.unlinkToDeath(l, 0);
33515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
33615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
33715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
33815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    };
33915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
34015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    public IGpsStatusProvider getGpsStatusProvider() {
34115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        return mGpsStatusProvider;
34215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
34315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
34429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
345105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        @Override public void onReceive(Context context, Intent intent) {
346105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            String action = intent.getAction();
347105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
34829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (action.equals(ALARM_WAKEUP)) {
34929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_WAKEUP");
35003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                startNavigating(false);
3510632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            } else if (action.equals(ALARM_TIMEOUT)) {
3520632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");
3530632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                hibernate();
3541e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {
3551e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                checkSmsSuplInit(intent);
3561e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
3571e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                checkWapSuplInit(intent);
3581e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja             }
359105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
36029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    };
361105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
3621e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void checkSmsSuplInit(Intent intent) {
3631e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        SmsMessage[] messages = Intents.getMessagesFromIntent(intent);
3641e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        for (int i=0; i <messages.length; i++) {
3651e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            byte[] supl_init = messages[i].getUserData();
3661e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            native_agps_ni_message(supl_init,supl_init.length);
3671e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
3681e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
3691e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
3701e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void checkWapSuplInit(Intent intent) {
3711e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        byte[] supl_init = (byte[]) intent.getExtra("data");
3721e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        native_agps_ni_message(supl_init,supl_init.length);
3731e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
3741e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean isSupported() {
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_is_supported();
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3794e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    public GpsLocationProvider(Context context, ILocationManager locationManager) {
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
381104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey        mNtpTime = NtpTrustedTime.getInstance(context);
38215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mLocationManager = locationManager;
38379e642e8ed75033eacc461633a8f4cd5157d25dfMike Lockwood        mNIHandler = new GpsNetInitiatedHandler(context);
38463598a0619776b421f27cd12fb29eb83dc327997Mike Lockwood
38563598a0619776b421f27cd12fb29eb83dc327997Mike Lockwood        mLocation.setExtras(mLocationExtras);
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3870528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // Create a wake lock
3880528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
3890528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
39098e48691f738680fe59e7383a41458e7337daccdMike Lockwood        mWakeLock.setReferenceCounted(false);
3910528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
39229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
39329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
3940632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
39529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
3961e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        IntentFilter intentFilter = new IntentFilter();
3971e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
3981e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter.addDataScheme("sms");
3991e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter.addDataAuthority("localhost","7275");
4001e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        context.registerReceiver(mBroadcastReciever, intentFilter);
4011e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
4021e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter = new IntentFilter();
4031e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
4041e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        try {
4051e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            intentFilter.addDataType("application/vnd.omaloc-supl-init");
4061e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        } catch (IntentFilter.MalformedMimeTypeException e) {
4071e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            Log.w(TAG, "Malformed SUPL init mime type");
4081e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
4091e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        context.registerReceiver(mBroadcastReciever, intentFilter);
4101e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
41158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
41258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
4132f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        // Battery statistics service to be notified when GPS turns on or off
4142f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
4152f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProperties = new Properties();
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            File file = new File(PROPERTIES_FILE);
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            FileInputStream stream = new FileInputStream(file);
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProperties.load(stream);
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stream.close();
422e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
423734d6031a662a275ec68627bd1258159041d44deMike Lockwood            mSuplServerHost = mProperties.getProperty("SUPL_HOST");
424e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            String portString = mProperties.getProperty("SUPL_PORT");
425734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mSuplServerHost != null && portString != null) {
426105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                try {
427734d6031a662a275ec68627bd1258159041d44deMike Lockwood                    mSuplServerPort = Integer.parseInt(portString);
428105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                } catch (NumberFormatException e) {
429e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
430e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                }
431e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            }
432e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
433734d6031a662a275ec68627bd1258159041d44deMike Lockwood            mC2KServerHost = mProperties.getProperty("C2K_HOST");
434e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            portString = mProperties.getProperty("C2K_PORT");
435734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mC2KServerHost != null && portString != null) {
436e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                try {
437734d6031a662a275ec68627bd1258159041d44deMike Lockwood                    mC2KServerPort = Integer.parseInt(portString);
438e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                } catch (NumberFormatException e) {
439e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse C2K_PORT: " + portString);
440105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                }
441105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
44562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
44689096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        // wait until we are fully initialized before returning
44789096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        mThread = new GpsLocationProviderThread();
44889096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        mThread.start();
44989096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        while (true) {
45089096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            try {
45189096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood                mInitializedLatch.await();
45289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood                break;
45389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            } catch (InterruptedException e) {
45489096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood                Thread.currentThread().interrupt();
45589096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            }
45689096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        }
45762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
45862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
45962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void initialize() {
46062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        // register our receiver on our thread rather than the main thread
46162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        IntentFilter intentFilter = new IntentFilter();
46262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        intentFilter.addAction(ALARM_WAKEUP);
46362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        intentFilter.addAction(ALARM_TIMEOUT);
46462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mContext.registerReceiver(mBroadcastReciever, intentFilter);
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
468d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood     * Returns the name of this provider.
469d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood     */
470d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    public String getName() {
471d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        return LocationManager.GPS_PROVIDER;
472d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    }
473d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood
474d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    /**
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to a
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * data network (e.g., the Internet), false otherwise.
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresNetwork() {
479a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood        return true;
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
48203d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood    public void updateNetworkState(int state, NetworkInfo info) {
48398e48691f738680fe59e7383a41458e7337daccdMike Lockwood        sendMessage(UPDATE_NETWORK_STATE, state, info);
48462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
48562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
48662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleUpdateNetworkState(int state, NetworkInfo info) {
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNetworkAvailable = (state == LocationProvider.AVAILABLE);
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
489f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) {
49003d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            Log.d(TAG, "updateNetworkState " + (mNetworkAvailable ? "available" : "unavailable")
49103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                + " info: " + info);
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
49303d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood
49450130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood        if (info != null) {
495a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            boolean dataEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
496a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                                                         Settings.Secure.MOBILE_DATA, 1) == 1;
497a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            boolean networkAvailable = info.isAvailable() && dataEnabled;
498a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            String defaultApn = getSelectedApn();
499a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            if (defaultApn == null) {
500a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                defaultApn = "dummy-apn";
501a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            }
502a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang
50350130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood            native_update_network_state(info.isConnected(), info.getType(),
504a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                                        info.isRoaming(), networkAvailable,
505a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                                        info.getExtraInfo(), defaultApn);
50650130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood        }
50750130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood
50803d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood        if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL
50903d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
51003d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            String apnName = info.getExtraInfo();
51183b69713f2dbeee7ff5e07836673a9a477be236fStephen Li            if (mNetworkAvailable) {
51283b69713f2dbeee7ff5e07836673a9a477be236fStephen Li                if (apnName == null) {
51383b69713f2dbeee7ff5e07836673a9a477be236fStephen Li                    /* Assign a dummy value in the case of C2K as otherwise we will have a runtime
51483b69713f2dbeee7ff5e07836673a9a477be236fStephen Li                    exception in the following call to native_agps_data_conn_open*/
51583b69713f2dbeee7ff5e07836673a9a477be236fStephen Li                    apnName = "dummy-apn";
51683b69713f2dbeee7ff5e07836673a9a477be236fStephen Li                }
51703d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsApn = apnName;
5188efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                if (DEBUG) Log.d(TAG, "mAGpsDataConnectionIpAddr " + mAGpsDataConnectionIpAddr);
5198efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                if (mAGpsDataConnectionIpAddr != 0xffffffff) {
5208efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                    boolean route_result;
5218efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                    if (DEBUG) Log.d(TAG, "call requestRouteToHost");
5228efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                    route_result = mConnMgr.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_SUPL,
5238efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                        mAGpsDataConnectionIpAddr);
5248efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                    if (route_result == false) Log.d(TAG, "call requestRouteToHost failed");
5258efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                }
52603d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                if (DEBUG) Log.d(TAG, "call native_agps_data_conn_open");
52703d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                native_agps_data_conn_open(apnName);
52803d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
52903d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            } else {
53003d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                if (DEBUG) Log.d(TAG, "call native_agps_data_conn_failed");
53103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsApn = null;
53203d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
53303d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                native_agps_data_conn_failed();
53403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            }
53503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood        }
53603d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood
53762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (mNetworkAvailable) {
53862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (mInjectNtpTimePending) {
53998e48691f738680fe59e7383a41458e7337daccdMike Lockwood                sendMessage(INJECT_NTP_TIME, 0, null);
54062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            }
54162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (mDownloadXtraDataPending) {
54298e48691f738680fe59e7383a41458e7337daccdMike Lockwood                sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
54362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            }
54462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
54562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
54662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
54762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleInjectNtpTime() {
54862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (!mNetworkAvailable) {
54962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            // try again when network is up
55062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mInjectNtpTimePending = true;
55162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            return;
55262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
55362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mInjectNtpTimePending = false;
55462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
55562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        long delay;
55662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
5572ffe0ad39127950074dc74bc5d15a284975da5aeMike Lockwood        // GPS requires fresh NTP time
5582ffe0ad39127950074dc74bc5d15a284975da5aeMike Lockwood        if (mNtpTime.forceRefresh()) {
559104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey            long time = mNtpTime.getCachedNtpTime();
560104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey            long timeReference = mNtpTime.getCachedNtpTimeReference();
561104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey            long certainty = mNtpTime.getCacheCertainty();
56262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            long now = System.currentTimeMillis();
56362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
56462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            Log.d(TAG, "NTP server returned: "
56562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    + time + " (" + new Date(time)
56662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    + ") reference: " + timeReference
56762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    + " certainty: " + certainty
5681879d284bf3dd704dbc8c95aad262ebbe3c3c0a4Mike Lockwood                    + " system time offset: " + (time - now));
56962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
570104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey            native_inject_time(time, timeReference, (int) certainty);
57162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            delay = NTP_INTERVAL;
57262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        } else {
57362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (DEBUG) Log.d(TAG, "requestTime failed");
57462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            delay = RETRY_INTERVAL;
57562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
57662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
5779b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood        if (mPeriodicTimeInjection) {
5789b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            // send delayed message for next NTP injection
5799b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            // since this is delayed and not urgent we do not hold a wake lock here
5809b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            mHandler.removeMessages(INJECT_NTP_TIME);
5819b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            mHandler.sendMessageDelayed(Message.obtain(mHandler, INJECT_NTP_TIME), delay);
5829b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood        }
58362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
58462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
58562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleDownloadXtraData() {
5865723dfe8c87d0887b8926f43637ed300466890d2Mike Lockwood        if (!mNetworkAvailable) {
58762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            // try again when network is up
58862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mDownloadXtraDataPending = true;
58962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            return;
59062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
59162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mDownloadXtraDataPending = false;
59262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
59362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
59462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
59562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        byte[] data = xtraDownloader.downloadXtraData();
59662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (data != null) {
59762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (DEBUG) {
59862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                Log.d(TAG, "calling native_inject_xtra_data");
59962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            }
60062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            native_inject_xtra_data(data, data.length);
60162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        } else {
60262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            // try again later
60398e48691f738680fe59e7383a41458e7337daccdMike Lockwood            // since this is delayed and not urgent we do not hold a wake lock here
60462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mHandler.removeMessages(DOWNLOAD_XTRA_DATA);
60562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mHandler.sendMessageDelayed(Message.obtain(mHandler, DOWNLOAD_XTRA_DATA), RETRY_INTERVAL);
60662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
610fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     * This is called to inform us when another location provider returns a location.
611fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     * Someday we might use this for network location injection to aid the GPS
612fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     */
613fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    public void updateLocation(Location location) {
61498e48691f738680fe59e7383a41458e7337daccdMike Lockwood        sendMessage(UPDATE_LOCATION, 0, location);
61562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
61662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
61762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleUpdateLocation(Location location) {
618d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        if (location.hasAccuracy()) {
619d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood            native_inject_location(location.getLatitude(), location.getLongitude(),
620d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood                    location.getAccuracy());
621d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        }
622fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    }
623fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood
624fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    /**
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to a
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * satellite-based positioning system (e.g., GPS), false
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise.
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresSatellite() {
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to an appropriate
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * cellular network (e.g., to make use of cell tower IDs), false
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise.
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresCell() {
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the use of this provider may result in a
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * monetary charge to the user, false if use is free.  It is up to
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * each provider to give accurate information.
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasMonetaryCost() {
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide altitude
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports altitude
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsAltitude() {
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
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 speed
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports speed
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 supportsSpeed() {
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 bearing
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports bearing
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 supportsBearing() {
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 the power requirement for this provider.
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the power requirement for this provider, as one of the
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * constants Criteria.POWER_REQUIREMENT_*.
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getPowerRequirement() {
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Criteria.POWER_HIGH;
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
69203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood     * Returns true if this provider meets the given criteria,
69303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood     * false otherwise.
69403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood     */
69503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public boolean meetsCriteria(Criteria criteria) {
69603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        return (criteria.getPowerRequirement() != Criteria.POWER_LOW);
69703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
69803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
69903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    /**
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the horizontal accuracy of this provider
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the accuracy of location from this provider, as one
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of the constants Criteria.ACCURACY_*.
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getAccuracy() {
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Criteria.ACCURACY_FINE;
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Enables this provider.  When enabled, calls to getStatus()
7114e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * must be handled.  Hardware may be started up
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the provider is enabled.
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
71462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    public void enable() {
71562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        synchronized (mHandler) {
71698e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(ENABLE, 1, null);
71762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
71862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
71962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
72062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleEnable() {
72162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (DEBUG) Log.d(TAG, "handleEnable");
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabled) return;
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnabled = native_init();
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabled) {
7261a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood            mSupportsXtra = native_supports_xtra();
727734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mSuplServerHost != null) {
728734d6031a662a275ec68627bd1258159041d44deMike Lockwood                native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
729734d6031a662a275ec68627bd1258159041d44deMike Lockwood            }
730734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mC2KServerHost != null) {
731734d6031a662a275ec68627bd1258159041d44deMike Lockwood                native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
732734d6031a662a275ec68627bd1258159041d44deMike Lockwood            }
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Failed to enable location provider");
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Disables this provider.  When disabled, calls to getStatus()
7404e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * need not be handled.  Hardware may be shut
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * down while the provider is disabled.
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
74362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    public void disable() {
74462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        synchronized (mHandler) {
74598e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(ENABLE, 0, null);
74662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
74762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
74862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
74962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleDisable() {
75089096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        if (DEBUG) Log.d(TAG, "handleDisable");
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mEnabled) return;
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnabled = false;
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        stopNavigating();
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
756cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood        // do this before releasing wakelock
757cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood        native_cleanup();
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
760d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    public boolean isEnabled() {
761d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        return mEnabled;
762d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    }
763d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getStatus(Bundle extras) {
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras != null) {
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            extras.putInt("satellites", mSvCount);
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatus;
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateStatus(int status, int svCount) {
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (status != mStatus || svCount != mSvCount) {
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatus = status;
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSvCount = svCount;
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationExtras.putInt("satellites", svCount);
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatusUpdateTime = SystemClock.elapsedRealtime();
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public long getStatusUpdateTime() {
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatusUpdateTime;
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void enableLocationTracking(boolean enable) {
78503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        // FIXME - should set a flag here to avoid race conditions with single shot request
78662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        synchronized (mHandler) {
78798e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(ENABLE_TRACKING, (enable ? 1 : 0), null);
78862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
78962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
79062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
79162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleEnableLocationTracking(boolean enable) {
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (enable) {
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = 0;
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
79503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            startNavigating(false);
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
79704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
79804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                mAlarmManager.cancel(mWakeupIntent);
79904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                mAlarmManager.cancel(mTimeoutIntent);
80004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            }
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stopNavigating();
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
80503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public boolean requestSingleShotFix() {
80603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        if (mStarted) {
80703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            // cannot do single shot if already navigating
80803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            return false;
80903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
81003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        synchronized (mHandler) {
81103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mHandler.removeMessages(REQUEST_SINGLE_SHOT);
81203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            Message m = Message.obtain(mHandler, REQUEST_SINGLE_SHOT);
81303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mHandler.sendMessage(m);
81403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
81503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        return true;
81603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
81703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
81803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private void handleRequestSingleShot() {
81903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        mTTFF = 0;
82003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        mLastFixTime = 0;
82103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        startNavigating(true);
82203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
82303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
8247e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn    public void setMinTime(long minTime, WorkSource ws) {
825f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) Log.d(TAG, "setMinTime " + minTime);
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (minTime >= 0) {
82804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            mFixInterval = (int)minTime;
82904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
83004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
83104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
83204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                        mFixInterval, 0, 0)) {
83304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                    Log.e(TAG, "set_position_mode failed in setMinTime()");
83404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                }
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8393c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    public String getInternalState() {
8403c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger        return native_get_internal_state();
8413c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    }
8423c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final class Listener implements IBinder.DeathRecipient {
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IGpsStatusListener mListener;
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int mSensors = 0;
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Listener(IGpsStatusListener listener) {
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = listener;
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
853f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato            if (DEBUG) Log.d(TAG, "GPS status listener died");
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(mListeners) {
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mListeners.remove(this);
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
858fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu            if (mListener != null) {
859fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu                mListener.asBinder().unlinkToDeath(this, 0);
860fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu            }
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8642f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    public void addListener(int uid) {
86598e48691f738680fe59e7383a41458e7337daccdMike Lockwood        synchronized (mWakeLock) {
86698e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mPendingListenerMessages++;
8677e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            mWakeLock.acquire();
86898e48691f738680fe59e7383a41458e7337daccdMike Lockwood            Message m = Message.obtain(mHandler, ADD_LISTENER);
86998e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.arg1 = uid;
87098e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.sendMessage(m);
87198e48691f738680fe59e7383a41458e7337daccdMike Lockwood        }
87262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
87362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
87462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleAddListener(int uid) {
8752e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
8762e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mClientUids.indexOfKey(uid) >= 0) {
8772e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                // Shouldn't be here -- already have this uid.
8782e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                Log.w(TAG, "Duplicate add listener for uid " + uid);
8792e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                return;
8802e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            }
8812e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            mClientUids.put(uid, 0);
8822e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mNavigating) {
8832e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
8842e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    mBatteryStats.noteStartGps(uid);
8852e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
8862e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in addListener");
8872e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                }
8882f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
8892f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
8902f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
8912f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8922f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    public void removeListener(int uid) {
89398e48691f738680fe59e7383a41458e7337daccdMike Lockwood        synchronized (mWakeLock) {
89498e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mPendingListenerMessages++;
89598e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mWakeLock.acquire();
89698e48691f738680fe59e7383a41458e7337daccdMike Lockwood            Message m = Message.obtain(mHandler, REMOVE_LISTENER);
89798e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.arg1 = uid;
89898e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.sendMessage(m);
89998e48691f738680fe59e7383a41458e7337daccdMike Lockwood        }
90062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
90162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
90262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleRemoveListener(int uid) {
9032e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
9042e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mClientUids.indexOfKey(uid) < 0) {
9052e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                // Shouldn't be here -- don't have this uid.
9062e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                Log.w(TAG, "Unneeded remove listener for uid " + uid);
9072e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                return;
9082e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            }
9092e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            mClientUids.delete(uid);
9102e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mNavigating) {
9112e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
9122e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    mBatteryStats.noteStopGps(uid);
9132e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
9142e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in removeListener");
9152e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                }
9162f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
9172f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
9182f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
9192f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendExtraCommand(String command, Bundle extras) {
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
92263aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        long identity = Binder.clearCallingIdentity();
92363aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        boolean result = false;
92463aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ("delete_aiding_data".equals(command)) {
92663aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood            result = deleteAidingData(extras);
92763aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        } else if ("force_time_injection".equals(command)) {
92898e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(INJECT_NTP_TIME, 0, null);
92963aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood            result = true;
93063aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        } else if ("force_xtra_injection".equals(command)) {
9311a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood            if (mSupportsXtra) {
93293bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                xtraDownloadRequest();
93363aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood                result = true;
93493bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            }
93563aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        } else {
93663aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood            Log.w(TAG, "sendExtraCommand: unknown command " + command);
93793bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
93963aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        Binder.restoreCallingIdentity(identity);
94063aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        return result;
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean deleteAidingData(Bundle extras) {
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags;
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras == null) {
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = GPS_DELETE_ALL;
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = 0;
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (flags != 0) {
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_delete_aiding_data(flags);
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
97303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private void startNavigating(boolean singleShot) {
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStarted) {
97529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (DEBUG) Log.d(TAG, "startNavigating");
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = true;
97703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mSingleShot = singleShot;
97803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mPositionMode = GPS_POSITION_MODE_STANDALONE;
97903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
98003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood             if (Settings.Secure.getInt(mContext.getContentResolver(),
981660bbfcc54d48d5d32e64da683c76b9c372c19b1Mike Lockwood                    Settings.Secure.ASSISTED_GPS_ENABLED, 1) != 0) {
98203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                if (singleShot && hasCapability(GPS_CAPABILITY_MSA)) {
98303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    mPositionMode = GPS_POSITION_MODE_MS_ASSISTED;
9848dc16c27e23dae5bdf65fd2a2ced97c2f645a633Mike Lockwood                } else if (hasCapability(GPS_CAPABILITY_MSB)) {
98503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    mPositionMode = GPS_POSITION_MODE_MS_BASED;
98603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                }
987bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood            }
988bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood
98904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
99004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
99104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                    interval, 0, 0)) {
99204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                mStarted = false;
99304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                Log.e(TAG, "set_position_mode failed in startNavigating()");
99404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                return;
99504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            }
99604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!native_start()) {
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStarted = false;
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.e(TAG, "native_start failed in startNavigating()");
9990632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                return;
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
100315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
100429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            mFixRequestTime = System.currentTimeMillis();
100504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
100604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
100704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                // and our fix interval is not short
100804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                if (mFixInterval >= NO_FIX_TIMEOUT) {
100904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                    mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
101004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                            SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
101104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                }
10120632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            }
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
101662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void stopNavigating() {
101729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (DEBUG) Log.d(TAG, "stopNavigating");
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mStarted) {
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = false;
102003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mSingleShot = false;
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_stop();
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = 0;
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = LOCATION_INVALID;
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
102715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10310632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private void hibernate() {
10320632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        // stop GPS until our next fix interval arrives
10330632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        stopNavigating();
10340632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mTimeoutIntent);
10350632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mWakeupIntent);
10360632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        long now = SystemClock.elapsedRealtime();
10370632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
103804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                SystemClock.elapsedRealtime() + mFixInterval, mWakeupIntent);
103904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    }
104004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
104104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private boolean hasCapability(int capability) {
104204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood        return ((mEngineCapabilities & capability) != 0);
10430632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    }
10440632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our position.
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportLocation(int flags, double latitude, double longitude, double altitude,
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float speed, float bearing, float accuracy, long timestamp) {
105029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                " timestamp: " + timestamp);
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mLocation) {
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = flags;
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLatitude(latitude);
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLongitude(longitude);
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setTime(timestamp);
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAltitude(altitude);
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAltitude();
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setSpeed(speed);
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeSpeed();
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setBearing(bearing);
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeBearing();
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAccuracy(accuracy);
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAccuracy();
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
108115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            try {
1082a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                mLocationManager.reportLocation(mLocation, false);
108315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            } catch (RemoteException e) {
108415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Log.e(TAG, "RemoteException calling reportLocation");
108515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1088fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        mLastFixTime = System.currentTimeMillis();
1089fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        // report time to first fix
1090fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        if (mTTFF == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1091fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            mTTFF = (int)(mLastFixTime - mFixRequestTime);
1092f4dffd8a45386b5a5f0e6de4f30facc9eaac4001The Android Open Source Project            if (DEBUG) Log.d(TAG, "TTFF: " + mTTFF);
1093fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson
1094fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            // notify status listeners
1095fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            synchronized(mListeners) {
1096fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                int size = mListeners.size();
1097fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                for (int i = 0; i < size; i++) {
1098fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    Listener listener = mListeners.get(i);
1099fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    try {
1100f4dffd8a45386b5a5f0e6de4f30facc9eaac4001The Android Open Source Project                        listener.mListener.onFirstFix(mTTFF);
1101fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    } catch (RemoteException e) {
1102fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        Log.w(TAG, "RemoteException in stopNavigating");
1103fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        mListeners.remove(listener);
1104fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        // adjust for size of list changing
1105fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        size--;
1106fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    }
1107fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                }
1108fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            }
1109fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        }
1110fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson
111103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        if (mSingleShot) {
111203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            stopNavigating();
111303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
111415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mStarted && mStatus != LocationProvider.AVAILABLE) {
1115d53ba017ee2381383b4bb4d92e6e0e661431660fMike Lockwood            // we want to time out if we do not receive a fix
1116b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood            // within the time out and we are requesting infrequent fixes
111704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {
1118b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood                mAlarmManager.cancel(mTimeoutIntent);
1119b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood            }
1120b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is receiving fixes.
112200b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
112300b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
112515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.AVAILABLE, mSvCount);
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
112729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
112803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood       if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted && mFixInterval > 1000) {
1129d53ba017ee2381383b4bb4d92e6e0e661431660fMike Lockwood            if (DEBUG) Log.d(TAG, "got fix, hibernating");
11300632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            hibernate();
113129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        }
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   }
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our status
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportStatus(int status) {
1138b8d9033d9928209e68518c4b12fea74187ddb382Mike Lockwood        if (DEBUG) Log.v(TAG, "reportStatus status: " + status);
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11402e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
11412e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            boolean wasNavigating = mNavigating;
1142dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood
1143cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            switch (status) {
1144cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_SESSION_BEGIN:
1145cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mNavigating = true;
1146271f9f172b241607b1ed39a7709c3ed47ee5dee7Mike Lockwood                    mEngineOn = true;
1147cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1148cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_SESSION_END:
1149cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mNavigating = false;
1150cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1151cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_ENGINE_ON:
1152cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mEngineOn = true;
1153cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1154cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_ENGINE_OFF:
1155cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mEngineOn = false;
1156271f9f172b241607b1ed39a7709c3ed47ee5dee7Mike Lockwood                    mNavigating = false;
1157cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1158cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            }
1159cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood
1160dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood            if (wasNavigating != mNavigating) {
1161dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                int size = mListeners.size();
1162dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                for (int i = 0; i < size; i++) {
1163dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    Listener listener = mListeners.get(i);
1164dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    try {
1165dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        if (mNavigating) {
1166dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            listener.mListener.onGpsStarted();
1167dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        } else {
1168dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            listener.mListener.onGpsStopped();
1169dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        }
1170dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    } catch (RemoteException e) {
1171dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        Log.w(TAG, "RemoteException in reportStatus");
1172dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        mListeners.remove(listener);
1173dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        // adjust for size of list changing
1174dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        size--;
1175dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    }
1176dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                }
1177dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood
11782e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
1179dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    // update battery stats
1180dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    for (int i=mClientUids.size() - 1; i >= 0; i--) {
1181dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        int uid = mClientUids.keyAt(i);
1182dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        if (mNavigating) {
1183dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            mBatteryStats.noteStartGps(uid);
1184dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        } else {
1185dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            mBatteryStats.noteStopGps(uid);
1186dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        }
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11882e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
11892e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in reportStatus");
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1192dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                // send an intent to notify that the GPS has been enabled or disabled.
119300b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood                Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
119400b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood                intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
1195dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                mContext.sendBroadcast(intent);
11962f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update SV info
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportSvStatus() {
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(mListeners) {
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int size = mListeners.size();
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < size; i++) {
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Listener listener = mListeners.get(i);
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs,
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSvElevations, mSvAzimuths, mSvMasks[EPHEMERIS_MASK],
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK]);
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.w(TAG, "RemoteException in reportSvInfo");
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mListeners.remove(listener);
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // adjust for size of list changing
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    size--;
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
122429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) {
122529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            Log.v(TAG, "SV count: " + svCount +
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) +
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK]));
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < svCount; i++) {
122929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                Log.v(TAG, "sv: " + mSvs[i] +
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " snr: " + (float)mSnrs[i]/10 +
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " elev: " + mSvElevations[i] +
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " azimuth: " + mSvAzimuths[i] +
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " E") +
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " A") +
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U"));
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12390881f4f9339febee85c9ab4cba69970ac5cbde55Kevin.KY Tsai        // return number of sets used in fix instead of total
12400881f4f9339febee85c9ab4cba69970ac5cbde55Kevin.KY Tsai        updateStatus(mStatus, Integer.bitCount(mSvMasks[USED_FOR_FIX_MASK]));
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
124215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
124304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is no longer receiving fixes.
124500b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
124600b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
124815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
125158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
125258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    /**
1253e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood     * called from native code to update AGPS status
125458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood     */
12558efd74dbedb65f69734318d9d6be70767f30b57aStephen Li    private void reportAGpsStatus(int type, int status, int ipaddr) {
125658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        switch (status) {
1257e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_REQUEST_AGPS_DATA_CONN:
1258b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
12592acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                // Set mAGpsDataConnectionState before calling startUsingNetworkFeature
12602acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                //  to avoid a race condition with handleUpdateNetworkState()
12612acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
12622acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                int result = mConnMgr.startUsingNetworkFeature(
126358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                        ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
12648efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                mAGpsDataConnectionIpAddr = ipaddr;
126558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                if (result == Phone.APN_ALREADY_ACTIVE) {
12662d4d1bf14b531de9d4238b1e41b53c77f8976405Mike Lockwood                    if (DEBUG) Log.d(TAG, "Phone.APN_ALREADY_ACTIVE");
1267b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    if (mAGpsApn != null) {
12688efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                        Log.d(TAG, "mAGpsDataConnectionIpAddr " + mAGpsDataConnectionIpAddr);
12698efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                        if (mAGpsDataConnectionIpAddr != 0xffffffff) {
12708efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                            boolean route_result;
12718efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                            if (DEBUG) Log.d(TAG, "call requestRouteToHost");
12728efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                            route_result = mConnMgr.requestRouteToHost(
12738efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                                ConnectivityManager.TYPE_MOBILE_SUPL,
12748efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                                mAGpsDataConnectionIpAddr);
12758efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                            if (route_result == false) Log.d(TAG, "call requestRouteToHost failed");
12768efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                        }
1277b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        native_agps_data_conn_open(mAGpsApn);
1278b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
1279b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    } else {
1280b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        Log.e(TAG, "mAGpsApn not set when receiving Phone.APN_ALREADY_ACTIVE");
12812acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
1282b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        native_agps_data_conn_failed();
1283b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    }
128458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else if (result == Phone.APN_REQUEST_STARTED) {
12854a7b65e0d544ef1feff8e1e5789f469f89ebb85cMike Lockwood                    if (DEBUG) Log.d(TAG, "Phone.APN_REQUEST_STARTED");
12862acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                    // Nothing to do here
128758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else {
1288b8d9033d9928209e68518c4b12fea74187ddb382Mike Lockwood                    if (DEBUG) Log.d(TAG, "startUsingNetworkFeature failed");
12892acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
1290e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_failed();
129158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
129258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1293e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_RELEASE_AGPS_DATA_CONN:
1294b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
1295e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
129658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                    mConnMgr.stopUsingNetworkFeature(
129758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                            ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
1298e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_closed();
1299e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
130058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
130158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1302e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONNECTED:
1303b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
130458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1305e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_DONE:
1306b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
130758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1308e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_FAILED:
1309b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
131058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
131158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        }
131258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    }
131358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1314b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    /**
1315b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood     * called from native code to report NMEA data received
1316b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood     */
1317f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood    private void reportNmea(long timestamp) {
1318b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood        synchronized(mListeners) {
1319b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            int size = mListeners.size();
1320b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            if (size > 0) {
1321b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                // don't bother creating the String if we have no listeners
1322f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood                int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
1323b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                String nmea = new String(mNmeaBuffer, 0, length);
1324b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood
1325b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                for (int i = 0; i < size; i++) {
1326b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    Listener listener = mListeners.get(i);
1327b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    try {
1328b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        listener.mListener.onNmeaReceived(timestamp, nmea);
1329b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    } catch (RemoteException e) {
1330b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        Log.w(TAG, "RemoteException in reportNmea");
1331b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        mListeners.remove(listener);
1332b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        // adjust for size of list changing
1333b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        size--;
1334b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    }
1335b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                }
1336b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            }
1337b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood        }
1338b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    }
1339b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood
134062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    /**
134104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood     * called from native code to inform us what the GPS engine capabilities are
134204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood     */
134304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private void setEngineCapabilities(int capabilities) {
134404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood        mEngineCapabilities = capabilities;
13459b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood
13469b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood        if (!hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME) && !mPeriodicTimeInjection) {
13479b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            mPeriodicTimeInjection = true;
13489b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            requestUtcTime();
13499b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood        }
135004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    }
135104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
135204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    /**
135362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood     * called from native code to request XTRA data
135462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood     */
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void xtraDownloadRequest() {
1356f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
135798e48691f738680fe59e7383a41458e7337daccdMike Lockwood        sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
136022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    //=============================================================
136122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // NI Client support
13621e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    //=============================================================
136322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
13641e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        // Sends a response for an NI reqeust to HAL.
13651e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        public boolean sendNiResponse(int notificationId, int userResponse)
13661e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        {
13671e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            // TODO Add Permission check
13681e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13691e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            StringBuilder extrasBuf = new StringBuilder();
13701e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13711e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
13721e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                    ", response: " + userResponse);
13731e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            native_send_ni_response(notificationId, userResponse);
13741e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            return true;
13751e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
137622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    };
137722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
137822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    public INetInitiatedListener getNetInitiatedListener() {
137922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        return mNetInitiatedListener;
138022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    }
138122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
138222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // Called by JNI function to report an NI request.
13831e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    public void reportNiNotification(
13841e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int notificationId,
13851e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int niType,
13861e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int notifyFlags,
13871e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int timeout,
13881e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int defaultResponse,
13891e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String requestorId,
13901e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String text,
13911e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int requestorIdEncoding,
13921e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int textEncoding,
13931e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String extras  // Encoded extra data
139422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        )
13951e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    {
13961e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Log.i(TAG, "reportNiNotification: entered");
13971e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Log.i(TAG, "notificationId: " + notificationId +
13981e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", niType: " + niType +
13991e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", notifyFlags: " + notifyFlags +
14001e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", timeout: " + timeout +
14011e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", defaultResponse: " + defaultResponse);
14021e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14031e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Log.i(TAG, "requestorId: " + requestorId +
14041e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", text: " + text +
14051e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", requestorIdEncoding: " + requestorIdEncoding +
14061e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", textEncoding: " + textEncoding);
14071e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14081e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        GpsNiNotification notification = new GpsNiNotification();
14091e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14101e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.notificationId = notificationId;
14111e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.niType = niType;
14121e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
14131e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
14141e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
14151e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.timeout = timeout;
14161e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.defaultResponse = defaultResponse;
14171e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.requestorId = requestorId;
14181e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.text = text;
14191e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.requestorIdEncoding = requestorIdEncoding;
14201e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.textEncoding = textEncoding;
14211e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14221e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        // Process extras, assuming the format is
14231e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        // one of more lines of "key = value"
14241e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Bundle bundle = new Bundle();
14251e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14261e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        if (extras == null) extras = "";
14271e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Properties extraProp = new Properties();
14281e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14291e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        try {
1430104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey            extraProp.load(new StringReader(extras));
14311e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
14321e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        catch (IOException e)
14331e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        {
14341e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
14351e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
14361e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14371e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        for (Entry<Object, Object> ent : extraProp.entrySet())
14381e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        {
14391e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            bundle.putString((String) ent.getKey(), (String) ent.getValue());
14401e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
14411e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14421e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.extras = bundle;
14431e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14441e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        mNIHandler.handleNiNotification(notification);
14451e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
14461e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14471e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    /**
14481e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * Called from native code to request set id info.
14491e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * We should be careful about receiving null string from the TelephonyManager,
14501e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * because sending null String to JNI function would cause a crash.
14511e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     */
14521e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14531e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void requestSetID(int flags) {
14541e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        TelephonyManager phone = (TelephonyManager)
14551e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                mContext.getSystemService(Context.TELEPHONY_SERVICE);
14561e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        int    type = AGPS_SETID_TYPE_NONE;
14571e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        String data = "";
14581e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14591e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
14601e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String data_temp = phone.getSubscriberId();
14611e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            if (data_temp == null) {
14621e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework does not have the SIM card ready.
14631e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else {
14641e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework has the SIM card.
14651e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                data = data_temp;
14661e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                type = AGPS_SETID_TYPE_IMSI;
14671e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            }
14681e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
14691e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
14701e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String data_temp = phone.getLine1Number();
14711e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            if (data_temp == null) {
14721e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework does not have the SIM card ready.
14731e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else {
14741e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework has the SIM card.
14751e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                data = data_temp;
14761e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                type = AGPS_SETID_TYPE_MSISDN;
14771e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            }
14781e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
14791e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        native_agps_set_id(type, data);
14801e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
14811e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14821e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    /**
14839b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood     * Called from native code to request utc time info
14849b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood     */
14859b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood
14869b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    private void requestUtcTime() {
14879b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood        sendMessage(INJECT_NTP_TIME, 0, null);
14889b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    }
14899b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood
14909b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    /**
14911e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * Called from native code to request reference location info
14921e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     */
14931e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14941e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void requestRefLocation(int flags) {
14951e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        TelephonyManager phone = (TelephonyManager)
14961e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                mContext.getSystemService(Context.TELEPHONY_SERVICE);
14971e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        if (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
14981e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation();
1499edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood            if ((gsm_cell != null) && (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) &&
1500edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                    (phone.getNetworkOperator() != null) &&
1501edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                        (phone.getNetworkOperator().length() > 3)) {
15021e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                int type;
15031e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0,3));
15041e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3));
1505edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                int networkType = phone.getNetworkType();
1506edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                if (networkType == TelephonyManager.NETWORK_TYPE_UMTS
1507edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                    || networkType == TelephonyManager.NETWORK_TYPE_HSDPA
1508edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                    || networkType == TelephonyManager.NETWORK_TYPE_HSUPA
1509edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                    || networkType == TelephonyManager.NETWORK_TYPE_HSPA) {
15101e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                    type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
1511edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                } else {
15121e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                    type = AGPS_REF_LOCATION_TYPE_GSM_CELLID;
1513edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                }
15141e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                native_agps_set_ref_location_cellid(type, mcc, mnc,
15151e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                        gsm_cell.getLac(), gsm_cell.getCid());
1516edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood            } else {
15171e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                Log.e(TAG,"Error getting cell location info.");
1518edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood            }
15191e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
1520edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood        else {
15211e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            Log.e(TAG,"CDMA not supported.");
1522edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood        }
15231e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
152422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
152598e48691f738680fe59e7383a41458e7337daccdMike Lockwood    private void sendMessage(int message, int arg, Object obj) {
152698e48691f738680fe59e7383a41458e7337daccdMike Lockwood        // hold a wake lock while messages are pending
152798e48691f738680fe59e7383a41458e7337daccdMike Lockwood        synchronized (mWakeLock) {
152898e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mPendingMessageBits |= (1 << message);
152998e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mWakeLock.acquire();
153098e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.removeMessages(message);
153198e48691f738680fe59e7383a41458e7337daccdMike Lockwood            Message m = Message.obtain(mHandler, message);
153298e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.arg1 = arg;
153398e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.obj = obj;
153498e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.sendMessage(m);
153598e48691f738680fe59e7383a41458e7337daccdMike Lockwood        }
153698e48691f738680fe59e7383a41458e7337daccdMike Lockwood    }
153798e48691f738680fe59e7383a41458e7337daccdMike Lockwood
153862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private final class ProviderHandler extends Handler {
153962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        @Override
15404a7b65e0d544ef1feff8e1e5789f469f89ebb85cMike Lockwood        public void handleMessage(Message msg) {
154198e48691f738680fe59e7383a41458e7337daccdMike Lockwood            int message = msg.what;
154298e48691f738680fe59e7383a41458e7337daccdMike Lockwood            switch (message) {
154362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case ENABLE:
154462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    if (msg.arg1 == 1) {
154562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                        handleEnable();
154662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    } else {
154762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                        handleDisable();
15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
154962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
155062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case ENABLE_TRACKING:
155162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleEnableLocationTracking(msg.arg1 == 1);
155262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
155303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                case REQUEST_SINGLE_SHOT:
155403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    handleRequestSingleShot();
155503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    break;
155662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case UPDATE_NETWORK_STATE:
155762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleUpdateNetworkState(msg.arg1, (NetworkInfo)msg.obj);
155862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
155962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case INJECT_NTP_TIME:
156062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleInjectNtpTime();
156162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
156262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case DOWNLOAD_XTRA_DATA:
15631a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood                    if (mSupportsXtra) {
156462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                        handleDownloadXtraData();
15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
156662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
156762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case UPDATE_LOCATION:
156862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleUpdateLocation((Location)msg.obj);
156962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
157062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case ADD_LISTENER:
157162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleAddListener(msg.arg1);
157262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
157362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case REMOVE_LISTENER:
157462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleRemoveListener(msg.arg1);
157562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
157798e48691f738680fe59e7383a41458e7337daccdMike Lockwood            // release wake lock if no messages are pending
157898e48691f738680fe59e7383a41458e7337daccdMike Lockwood            synchronized (mWakeLock) {
157998e48691f738680fe59e7383a41458e7337daccdMike Lockwood                mPendingMessageBits &= ~(1 << message);
158098e48691f738680fe59e7383a41458e7337daccdMike Lockwood                if (message == ADD_LISTENER || message == REMOVE_LISTENER) {
158198e48691f738680fe59e7383a41458e7337daccdMike Lockwood                    mPendingListenerMessages--;
158298e48691f738680fe59e7383a41458e7337daccdMike Lockwood                }
158398e48691f738680fe59e7383a41458e7337daccdMike Lockwood                if (mPendingMessageBits == 0 && mPendingListenerMessages == 0) {
158498e48691f738680fe59e7383a41458e7337daccdMike Lockwood                    mWakeLock.release();
158598e48691f738680fe59e7383a41458e7337daccdMike Lockwood                }
158698e48691f738680fe59e7383a41458e7337daccdMike Lockwood            }
15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
158862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    };
15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
159089096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private final class GpsLocationProviderThread extends Thread {
159189096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood
159289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        public GpsLocationProviderThread() {
159389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            super("GpsLocationProvider");
159489096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        }
159589096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood
159689096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        public void run() {
159789096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
159889096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            initialize();
159989096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            Looper.prepare();
160089096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            mHandler = new ProviderHandler();
160189096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            // signal when we are initialized and ready to go
160289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            mInitializedLatch.countDown();
160389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            Looper.loop();
160489096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        }
16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1607a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang    private String getSelectedApn() {
1608a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang        Uri uri = Uri.parse("content://telephony/carriers/preferapn");
1609a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang        String apn = null;
1610a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang
1611a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang        Cursor cursor = mContext.getContentResolver().query(uri, new String[] {"apn"},
1612a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                null, null, Carriers.DEFAULT_SORT_ORDER);
1613a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang
1614a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang        if (null != cursor) {
1615a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            try {
1616a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                if (cursor.moveToFirst()) {
1617a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                    apn = cursor.getString(0);
1618a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                }
1619a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            } finally {
1620a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                cursor.close();
1621a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            }
1622a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang        }
1623a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang        return apn;
1624a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang    }
1625a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for GPS SV statistics
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int MAX_SVS = 32;
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int EPHEMERIS_MASK = 0;
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int ALMANAC_MASK = 1;
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int USED_FOR_FIX_MASK = 2;
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // preallocated arrays, to avoid memory allocation in reportStatus()
16339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvs[] = new int[MAX_SVS];
16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSnrs[] = new float[MAX_SVS];
16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvElevations[] = new float[MAX_SVS];
16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvAzimuths[] = new float[MAX_SVS];
16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvMasks[] = new int[3];
16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvCount;
1639b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    // preallocated to avoid memory allocation in reportNmea()
1640b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    private byte[] mNmeaBuffer = new byte[120];
16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static { class_init_native(); }
16439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native void class_init_native();
16449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native boolean native_is_supported();
16459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_init();
16479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_cleanup();
164804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private native boolean native_set_position_mode(int mode, int recurrence, int min_interval,
164904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            int preferred_accuracy, int preferred_time);
165004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private native boolean native_start();
16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_stop();
16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_delete_aiding_data(int flags);
16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // returns number of SVs
16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // mask[0] is ephemeris mask and mask[1] is almanac mask
16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native int native_read_sv_status(int[] svs, float[] snrs,
16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] elevations, float[] azimuths, int[] masks);
1657f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood    private native int native_read_nmea(byte[] buffer, int bufferSize);
1658d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood    private native void native_inject_location(double latitude, double longitude, float accuracy);
1659d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood
16603c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    // XTRA Support
16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_time(long time, long timeReference, int uncertainty);
16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_supports_xtra();
16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_xtra_data(byte[] data, int length);
1664105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
16653c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    // DEBUG Support
16663c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    private native String native_get_internal_state();
16673c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger
16683c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    // AGPS Support
1669e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_open(String apn);
1670e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_closed();
1671e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_failed();
16721e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private native void native_agps_ni_message(byte [] msg, int length);
1673a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood    private native void native_set_agps_server(int type, String hostname, int port);
167422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
167522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // Network-initiated (NI) Support
167622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private native void native_send_ni_response(int notificationId, int userResponse);
16771e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
16781e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // AGPS ril suport
16791e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
16801e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int lac, int cid);
16811e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private native void native_agps_set_id(int type, String setid);
168250130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood
168350130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood    private native void native_update_network_state(boolean connected, int type,
1684a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            boolean roaming, boolean available, String extraInfo, String defaultAPN);
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1686