GpsLocationProvider.java revision 50130bbc884a7ad7db39dbc4f54e76e8be87761f
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;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Criteria;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.IGpsStatusListener;
2715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwoodimport android.location.IGpsStatusProvider;
284e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwoodimport android.location.ILocationManager;
2922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport android.location.INetInitiatedListener;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Location;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationManager;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationProvider;
3358bda987665af759c379cd494ff4873ac61acf29Mike Lockwoodimport android.net.ConnectivityManager;
3403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwoodimport android.net.NetworkInfo;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.SntpClient;
3663aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwoodimport android.os.Binder;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
3862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwoodimport android.os.Handler;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
4062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwoodimport android.os.Looper;
4162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwoodimport android.os.Message;
420528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwoodimport android.os.PowerManager;
4362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwoodimport android.os.Process;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
452f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport android.os.ServiceManager;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
477e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackbornimport android.os.WorkSource;
48bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwoodimport android.provider.Settings;
491e84da822e7aa4d494b31c8759917d2751611f84Miguel Torrojaimport android.provider.Telephony.Sms.Intents;
501e84da822e7aa4d494b31c8759917d2751611f84Miguel Torrojaimport android.telephony.TelephonyManager;
511e84da822e7aa4d494b31c8759917d2751611f84Miguel Torrojaimport android.telephony.gsm.GsmCellLocation;
521e84da822e7aa4d494b31c8759917d2751611f84Miguel Torrojaimport android.telephony.SmsMessage;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
542f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport android.util.SparseIntArray;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
562f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport com.android.internal.app.IBatteryStats;
57105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport com.android.internal.telephony.Phone;
5822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport com.android.internal.location.GpsNetInitiatedHandler;
5922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
601e84da822e7aa4d494b31c8759917d2751611f84Miguel Torrojaimport com.android.internal.telephony.GsmAlphabet;
611e84da822e7aa4d494b31c8759917d2751611f84Miguel Torrojaimport com.android.internal.telephony.SmsHeader;
621e84da822e7aa4d494b31c8759917d2751611f84Miguel Torrojaimport com.android.internal.util.HexDump;
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;
6722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport java.io.StringBufferInputStream;
68105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport java.net.InetAddress;
69105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport java.net.UnknownHostException;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
71f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwoodimport java.util.Date;
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Properties;
7322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport java.util.Map.Entry;
7489096317104722219f73a5c3cc424e6e98c90a61Mike Lockwoodimport java.util.concurrent.CountDownLatch;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A GPS implementation of LocationProvider used by LocationManager.
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
8189096317104722219f73a5c3cc424e6e98c90a61Mike Lockwoodpublic class GpsLocationProvider implements LocationProviderInterface {
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "GpsLocationProvider";
8429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
85f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato    private static final boolean DEBUG = false;
8629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private static final boolean VERBOSE = false;
8762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
88105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    // these need to match GpsPositionMode enum in gps.h
89105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_STANDALONE = 0;
90105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_MS_BASED = 1;
91105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
92105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
9304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // these need to match GpsPositionRecurrence enum in gps.h
9404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_POSITION_RECURRENCE_PERIODIC = 0;
9504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_POSITION_RECURRENCE_SINGLE = 1;
9604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these need to match GpsStatusValue defines in gps.h
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_NONE = 0;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_SESSION_BEGIN = 1;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_SESSION_END = 2;
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_ENGINE_ON = 3;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_ENGINE_OFF = 4;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
104e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // these need to match GpsApgsStatusValue defines in gps.h
105e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    /** AGPS status event values. */
106e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
107e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
108e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONNECTED = 3;
109e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONN_DONE = 4;
110e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
11158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these need to match GpsLocationFlags enum in gps.h
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_INVALID = 0;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_LAT_LONG = 1;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_ALTITUDE = 2;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_SPEED = 4;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_BEARING = 8;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_ACCURACY = 16;
119e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
120e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood// IMPORTANT - the GPS_DELETE_* symbols here must match constants in gps.h
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_EPHEMERIS = 0x0001;
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_ALMANAC = 0x0002;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_POSITION = 0x0004;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_TIME = 0x0008;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_IONO = 0x0010;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_UTC = 0x0020;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_HEALTH = 0x0040;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SVDIR = 0x0080;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SVSTEER = 0x0100;
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SADATA = 0x0200;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_RTI = 0x0400;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_ALL = 0xFFFF;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // The GPS_CAPABILITY_* flags must match the values in gps.h
13604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_SCHEDULING = 0x0000001;
13704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_MSB = 0x0000002;
13804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_MSA = 0x0000004;
13904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
14004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
14104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
142e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // these need to match AGpsType enum in gps.h
143e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_TYPE_SUPL = 1;
144e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_TYPE_C2K = 2;
145e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
146e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // for mAGpsDataConnectionState
147e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
148e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_OPENING = 1;
149e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_OPEN = 2;
15058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
15162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    // Handler messages
15262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int CHECK_LOCATION = 1;
15362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int ENABLE = 2;
15462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int ENABLE_TRACKING = 3;
15562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int UPDATE_NETWORK_STATE = 4;
15662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int INJECT_NTP_TIME = 5;
15762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int DOWNLOAD_XTRA_DATA = 6;
15862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int UPDATE_LOCATION = 7;
15962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int ADD_LISTENER = 8;
16062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int REMOVE_LISTENER = 9;
16103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private static final int REQUEST_SINGLE_SHOT = 10;
16262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
1631e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // Request setid
1641e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
1651e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2;
1661e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
1671e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // Request ref location
1681e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_RIL_REQUEST_REFLOC_CELLID = 1;
1691e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_RIL_REQUEST_REFLOC_MAC = 2;
1701e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
1711e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // ref. location info
1721e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
1731e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
1741e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_REG_LOCATION_TYPE_MAC        = 3;
1751e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
1761e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // set id info
1771e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_SETID_TYPE_NONE = 0;
1781e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_SETID_TYPE_IMSI = 1;
1791e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_SETID_TYPE_MSISDN = 2;
1801e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String PROPERTIES_FILE = "/etc/gps.conf";
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mLocationFlags = LOCATION_INVALID;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current status
18615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time for last status update
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mStatusUpdateTime = SystemClock.elapsedRealtime();
190d53ba017ee2381383b4bb4d92e6e0e661431660fMike Lockwood
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // turn off GPS fix icon if we haven't received a fix in 10 seconds
19204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final long RECENT_FIX_TIMEOUT = 10 * 1000;
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1940632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    // stop trying if we do not receive a fix within 60 seconds
19504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int NO_FIX_TIMEOUT = 60 * 1000;
1960632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we are enabled
19889096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private volatile boolean mEnabled;
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we have network connectivity
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNetworkAvailable;
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    // flags to trigger NTP or XTRA data download when network becomes available
20462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    // initialized to true so we do NTP and XTRA when the network comes up after booting
20562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private boolean mInjectNtpTimePending = true;
2065723dfe8c87d0887b8926f43637ed300466890d2Mike Lockwood    private boolean mDownloadXtraDataPending = false;
20762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if GPS is navigating
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNavigating;
210cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood
211cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood    // true if GPS engine is on
212cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood    private boolean mEngineOn;
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // requested frequency of fixes, in milliseconds
21504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private int mFixInterval = 1000;
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we started navigation
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mStarted;
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    // true if single shot request is in progress
22103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private boolean mSingleShot;
22203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
22304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // capabilities of the GPS engine
22404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private int mEngineCapabilities;
22504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
2261a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood    // true if XTRA is supported
2271a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood    private boolean mSupportsXtra;
2281a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for calculating time to first fix
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mFixRequestTime = 0;
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time to first fix for most recent session
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mTTFF = 0;
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time we received our last fix
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mLastFixTime;
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private int mPositionMode;
23704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // properties loaded from PROPERTIES_FILE
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Properties mProperties;
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String mNtpServer;
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;
24715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final ILocationManager mLocationManager;
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Bundle mLocationExtras = new Bundle();
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<Listener> mListeners = new ArrayList<Listener>();
25162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
25289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    // GpsLocationProvider's handler thread
25389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private final Thread mThread;
25489096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    // Handler for processing events in mThread.
25562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private Handler mHandler;
25689096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    // Used to signal when our main thread has initialized everything
25789096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private final CountDownLatch mInitializedLatch = new CountDownLatch(1);
258105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
259e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private String mAGpsApn;
260e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private int mAGpsDataConnectionState;
2612f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final ConnectivityManager mConnMgr;
26222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private final GpsNetInitiatedHandler mNIHandler;
2632f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
2640528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    // Wakelocks
2650528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final static String WAKELOCK_KEY = "GpsLocationProvider";
2660528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final PowerManager.WakeLock mWakeLock;
26798e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // bitfield of pending messages to our Handler
26898e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // used only for messages that cannot have multiple instances queued
26998e48691f738680fe59e7383a41458e7337daccdMike Lockwood    private int mPendingMessageBits;
27098e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // separate counter for ADD_LISTENER and REMOVE_LISTENER messages,
27198e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // which might have multiple instances queued
27298e48691f738680fe59e7383a41458e7337daccdMike Lockwood    private int mPendingListenerMessages;
2730528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
27429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    // Alarms
27529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
2760632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
27729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final AlarmManager mAlarmManager;
27829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final PendingIntent mWakeupIntent;
2790632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final PendingIntent mTimeoutIntent;
28029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
2812f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final IBatteryStats mBatteryStats;
2822f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final SparseIntArray mClientUids = new SparseIntArray();
283105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // how often to request NTP time, in milliseconds
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current setting 4 hours
286f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood    private static final long NTP_INTERVAL = 4*60*60*1000;
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // how long to wait if we have a network error in NTP or XTRA downloading
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current setting - 5 minutes
289f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood    private static final long RETRY_INTERVAL = 5*60*1000;
290f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood
291f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood    // to avoid injecting bad NTP time, we reject any time fixes that differ from system time
292f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood    // by more than 5 minutes.
293f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood    private static final long MAX_NTP_SYSTEM_TIME_OFFSET = 5*60*1000;
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
29515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
29615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
29715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
29815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
29915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
30015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
30115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            synchronized(mListeners) {
30215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
30315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
30415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size; i++) {
30515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
30615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
30715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        // listener already added
30815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        return;
30915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
31015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
31115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
31215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = new Listener(listener);
31315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                binder.linkToDeath(l, 0);
31415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                mListeners.add(l);
31515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
31615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
31715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
31815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void removeGpsStatusListener(IGpsStatusListener listener) {
31915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
32015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
32115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
32215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
32315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            synchronized(mListeners) {
32415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
32515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = null;
32615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
32715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size && l == null; i++) {
32815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
32915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
33015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        l = test;
33115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
33215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
33315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
33415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                if (l != null) {
33515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    mListeners.remove(l);
33615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    binder.unlinkToDeath(l, 0);
33715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
33815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
33915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
34015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    };
34115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
34215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    public IGpsStatusProvider getGpsStatusProvider() {
34315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        return mGpsStatusProvider;
34415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
34515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
34629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
347105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        @Override public void onReceive(Context context, Intent intent) {
348105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            String action = intent.getAction();
349105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
35029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (action.equals(ALARM_WAKEUP)) {
35129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_WAKEUP");
35203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                startNavigating(false);
3530632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            } else if (action.equals(ALARM_TIMEOUT)) {
3540632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");
3550632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                hibernate();
3561e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {
3571e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                checkSmsSuplInit(intent);
3581e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
3591e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                checkWapSuplInit(intent);
3601e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja             }
361105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
36229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    };
363105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
3641e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void checkSmsSuplInit(Intent intent) {
3651e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        SmsMessage[] messages = Intents.getMessagesFromIntent(intent);
3661e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        for (int i=0; i <messages.length; i++) {
3671e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            byte[] supl_init = messages[i].getUserData();
3681e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            native_agps_ni_message(supl_init,supl_init.length);
3691e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
3701e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
3711e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
3721e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void checkWapSuplInit(Intent intent) {
3731e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        byte[] supl_init = (byte[]) intent.getExtra("data");
3741e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        native_agps_ni_message(supl_init,supl_init.length);
3751e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
3761e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean isSupported() {
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_is_supported();
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3814e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    public GpsLocationProvider(Context context, ILocationManager locationManager) {
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
38315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mLocationManager = locationManager;
38479e642e8ed75033eacc461633a8f4cd5157d25dfMike Lockwood        mNIHandler = new GpsNetInitiatedHandler(context);
38563598a0619776b421f27cd12fb29eb83dc327997Mike Lockwood
38663598a0619776b421f27cd12fb29eb83dc327997Mike Lockwood        mLocation.setExtras(mLocationExtras);
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3880528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // Create a wake lock
3890528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
3900528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
39198e48691f738680fe59e7383a41458e7337daccdMike Lockwood        mWakeLock.setReferenceCounted(false);
3920528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
39329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
39429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
3950632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
39629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
3971e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        IntentFilter intentFilter = new IntentFilter();
3981e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
3991e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter.addDataScheme("sms");
4001e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter.addDataAuthority("localhost","7275");
4011e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        context.registerReceiver(mBroadcastReciever, intentFilter);
4021e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
4031e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter = new IntentFilter();
4041e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
4051e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        try {
4061e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            intentFilter.addDataType("application/vnd.omaloc-supl-init");
4071e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        } catch (IntentFilter.MalformedMimeTypeException e) {
4081e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            Log.w(TAG, "Malformed SUPL init mime type");
4091e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
4101e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        context.registerReceiver(mBroadcastReciever, intentFilter);
4111e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
41258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
41358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
4142f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        // Battery statistics service to be notified when GPS turns on or off
4152f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
4162f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProperties = new Properties();
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            File file = new File(PROPERTIES_FILE);
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            FileInputStream stream = new FileInputStream(file);
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProperties.load(stream);
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stream.close();
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNtpServer = mProperties.getProperty("NTP_SERVER", null);
424e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
425734d6031a662a275ec68627bd1258159041d44deMike Lockwood            mSuplServerHost = mProperties.getProperty("SUPL_HOST");
426e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            String portString = mProperties.getProperty("SUPL_PORT");
427734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mSuplServerHost != null && portString != null) {
428105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                try {
429734d6031a662a275ec68627bd1258159041d44deMike Lockwood                    mSuplServerPort = Integer.parseInt(portString);
430105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                } catch (NumberFormatException e) {
431e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
432e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                }
433e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            }
434e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
435734d6031a662a275ec68627bd1258159041d44deMike Lockwood            mC2KServerHost = mProperties.getProperty("C2K_HOST");
436e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            portString = mProperties.getProperty("C2K_PORT");
437734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mC2KServerHost != null && portString != null) {
438e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                try {
439734d6031a662a275ec68627bd1258159041d44deMike Lockwood                    mC2KServerPort = Integer.parseInt(portString);
440e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                } catch (NumberFormatException e) {
441e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse C2K_PORT: " + portString);
442105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                }
443105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
44762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
44889096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        // wait until we are fully initialized before returning
44989096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        mThread = new GpsLocationProviderThread();
45089096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        mThread.start();
45189096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        while (true) {
45289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            try {
45389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood                mInitializedLatch.await();
45489096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood                break;
45589096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            } catch (InterruptedException e) {
45689096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood                Thread.currentThread().interrupt();
45789096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            }
45889096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        }
45962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
46062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
46162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void initialize() {
46262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        // register our receiver on our thread rather than the main thread
46362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        IntentFilter intentFilter = new IntentFilter();
46462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        intentFilter.addAction(ALARM_WAKEUP);
46562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        intentFilter.addAction(ALARM_TIMEOUT);
46662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mContext.registerReceiver(mBroadcastReciever, intentFilter);
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
470d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood     * Returns the name of this provider.
471d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood     */
472d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    public String getName() {
473d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        return LocationManager.GPS_PROVIDER;
474d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    }
475d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood
476d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    /**
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to a
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * data network (e.g., the Internet), false otherwise.
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresNetwork() {
481a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood        return true;
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
48403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood    public void updateNetworkState(int state, NetworkInfo info) {
48598e48691f738680fe59e7383a41458e7337daccdMike Lockwood        sendMessage(UPDATE_NETWORK_STATE, state, info);
48662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
48762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
48862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleUpdateNetworkState(int state, NetworkInfo info) {
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNetworkAvailable = (state == LocationProvider.AVAILABLE);
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
491f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) {
49203d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            Log.d(TAG, "updateNetworkState " + (mNetworkAvailable ? "available" : "unavailable")
49303d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                + " info: " + info);
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
49503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood
49650130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood        if (info != null) {
49750130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood            native_update_network_state(info.isConnected(), info.getType(),
49850130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood                    info.isRoaming(), info.getExtraInfo());
49950130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood        }
50050130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood
50103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood        if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL
50203d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
50303d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            String apnName = info.getExtraInfo();
50403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            if (mNetworkAvailable && apnName != null && apnName.length() > 0) {
50503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsApn = apnName;
50603d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                if (DEBUG) Log.d(TAG, "call native_agps_data_conn_open");
50703d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                native_agps_data_conn_open(apnName);
50803d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
50903d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            } else {
51003d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                if (DEBUG) Log.d(TAG, "call native_agps_data_conn_failed");
51103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsApn = null;
51203d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
51303d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                native_agps_data_conn_failed();
51403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            }
51503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood        }
51603d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood
51762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (mNetworkAvailable) {
51862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (mInjectNtpTimePending) {
51998e48691f738680fe59e7383a41458e7337daccdMike Lockwood                sendMessage(INJECT_NTP_TIME, 0, null);
52062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            }
52162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (mDownloadXtraDataPending) {
52298e48691f738680fe59e7383a41458e7337daccdMike Lockwood                sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
52362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            }
52462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
52562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
52662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
52762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleInjectNtpTime() {
52862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (!mNetworkAvailable) {
52962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            // try again when network is up
53062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mInjectNtpTimePending = true;
53162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            return;
53262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
53362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mInjectNtpTimePending = false;
53462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
53562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        SntpClient client = new SntpClient();
53662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        long delay;
53762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
53862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (client.requestTime(mNtpServer, 10000)) {
53962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            long time = client.getNtpTime();
54062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            long timeReference = client.getNtpTimeReference();
54162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            int certainty = (int)(client.getRoundTripTime()/2);
54262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            long now = System.currentTimeMillis();
54362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
54462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            Log.d(TAG, "NTP server returned: "
54562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    + time + " (" + new Date(time)
54662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    + ") reference: " + timeReference
54762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    + " certainty: " + certainty
5481879d284bf3dd704dbc8c95aad262ebbe3c3c0a4Mike Lockwood                    + " system time offset: " + (time - now));
54962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
5501879d284bf3dd704dbc8c95aad262ebbe3c3c0a4Mike Lockwood            native_inject_time(time, timeReference, certainty);
55162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            delay = NTP_INTERVAL;
55262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        } else {
55362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (DEBUG) Log.d(TAG, "requestTime failed");
55462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            delay = RETRY_INTERVAL;
55562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
55662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
55762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        // send delayed message for next NTP injection
55898e48691f738680fe59e7383a41458e7337daccdMike Lockwood        // since this is delayed and not urgent we do not hold a wake lock here
55962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mHandler.removeMessages(INJECT_NTP_TIME);
56062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mHandler.sendMessageDelayed(Message.obtain(mHandler, INJECT_NTP_TIME), delay);
56162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
56262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
56362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleDownloadXtraData() {
5645723dfe8c87d0887b8926f43637ed300466890d2Mike Lockwood        if (!mNetworkAvailable) {
56562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            // try again when network is up
56662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mDownloadXtraDataPending = true;
56762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            return;
56862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
56962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mDownloadXtraDataPending = false;
57062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
57162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
57262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
57362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        byte[] data = xtraDownloader.downloadXtraData();
57462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (data != null) {
57562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (DEBUG) {
57662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                Log.d(TAG, "calling native_inject_xtra_data");
57762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            }
57862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            native_inject_xtra_data(data, data.length);
57962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        } else {
58062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            // try again later
58198e48691f738680fe59e7383a41458e7337daccdMike Lockwood            // since this is delayed and not urgent we do not hold a wake lock here
58262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mHandler.removeMessages(DOWNLOAD_XTRA_DATA);
58362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mHandler.sendMessageDelayed(Message.obtain(mHandler, DOWNLOAD_XTRA_DATA), RETRY_INTERVAL);
58462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
588fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     * This is called to inform us when another location provider returns a location.
589fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     * Someday we might use this for network location injection to aid the GPS
590fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     */
591fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    public void updateLocation(Location location) {
59298e48691f738680fe59e7383a41458e7337daccdMike Lockwood        sendMessage(UPDATE_LOCATION, 0, location);
59362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
59462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
59562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleUpdateLocation(Location location) {
596d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        if (location.hasAccuracy()) {
597d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood            native_inject_location(location.getLatitude(), location.getLongitude(),
598d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood                    location.getAccuracy());
599d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        }
600fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    }
601fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood
602fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    /**
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to a
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * satellite-based positioning system (e.g., GPS), false
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise.
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresSatellite() {
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to an appropriate
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * cellular network (e.g., to make use of cell tower IDs), false
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise.
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresCell() {
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the use of this provider may result in a
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * monetary charge to the user, false if use is free.  It is up to
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * each provider to give accurate information.
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasMonetaryCost() {
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide altitude
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports altitude
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsAltitude() {
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide speed
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports speed
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsSpeed() {
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide bearing
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports bearing
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsBearing() {
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the power requirement for this provider.
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the power requirement for this provider, as one of the
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * constants Criteria.POWER_REQUIREMENT_*.
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getPowerRequirement() {
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Criteria.POWER_HIGH;
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
67003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood     * Returns true if this provider meets the given criteria,
67103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood     * false otherwise.
67203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood     */
67303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public boolean meetsCriteria(Criteria criteria) {
67403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        return (criteria.getPowerRequirement() != Criteria.POWER_LOW);
67503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
67603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
67703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    /**
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the horizontal accuracy of this provider
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the accuracy of location from this provider, as one
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of the constants Criteria.ACCURACY_*.
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getAccuracy() {
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Criteria.ACCURACY_FINE;
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Enables this provider.  When enabled, calls to getStatus()
6894e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * must be handled.  Hardware may be started up
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the provider is enabled.
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
69262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    public void enable() {
69362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        synchronized (mHandler) {
69498e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(ENABLE, 1, null);
69562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
69662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
69762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
69862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleEnable() {
69962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (DEBUG) Log.d(TAG, "handleEnable");
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabled) return;
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnabled = native_init();
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabled) {
7041a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood            mSupportsXtra = native_supports_xtra();
705734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mSuplServerHost != null) {
706734d6031a662a275ec68627bd1258159041d44deMike Lockwood                native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
707734d6031a662a275ec68627bd1258159041d44deMike Lockwood            }
708734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mC2KServerHost != null) {
709734d6031a662a275ec68627bd1258159041d44deMike Lockwood                native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
710734d6031a662a275ec68627bd1258159041d44deMike Lockwood            }
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Failed to enable location provider");
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Disables this provider.  When disabled, calls to getStatus()
7184e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * need not be handled.  Hardware may be shut
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * down while the provider is disabled.
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
72162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    public void disable() {
72262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        synchronized (mHandler) {
72398e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(ENABLE, 0, null);
72462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
72562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
72662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
72762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleDisable() {
72889096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        if (DEBUG) Log.d(TAG, "handleDisable");
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mEnabled) return;
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnabled = false;
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        stopNavigating();
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
734cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood        // do this before releasing wakelock
735cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood        native_cleanup();
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
738d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    public boolean isEnabled() {
739d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        return mEnabled;
740d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    }
741d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getStatus(Bundle extras) {
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras != null) {
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            extras.putInt("satellites", mSvCount);
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatus;
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateStatus(int status, int svCount) {
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (status != mStatus || svCount != mSvCount) {
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatus = status;
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSvCount = svCount;
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationExtras.putInt("satellites", svCount);
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatusUpdateTime = SystemClock.elapsedRealtime();
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public long getStatusUpdateTime() {
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatusUpdateTime;
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void enableLocationTracking(boolean enable) {
76303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        // FIXME - should set a flag here to avoid race conditions with single shot request
76462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        synchronized (mHandler) {
76598e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(ENABLE_TRACKING, (enable ? 1 : 0), null);
76662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
76762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
76862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
76962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleEnableLocationTracking(boolean enable) {
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (enable) {
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = 0;
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
77303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            startNavigating(false);
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
77504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
77604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                mAlarmManager.cancel(mWakeupIntent);
77704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                mAlarmManager.cancel(mTimeoutIntent);
77804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            }
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stopNavigating();
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
78303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public boolean requestSingleShotFix() {
78403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        if (mStarted) {
78503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            // cannot do single shot if already navigating
78603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            return false;
78703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
78803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        synchronized (mHandler) {
78903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mHandler.removeMessages(REQUEST_SINGLE_SHOT);
79003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            Message m = Message.obtain(mHandler, REQUEST_SINGLE_SHOT);
79103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mHandler.sendMessage(m);
79203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
79303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        return true;
79403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
79503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
79603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private void handleRequestSingleShot() {
79703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        mTTFF = 0;
79803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        mLastFixTime = 0;
79903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        startNavigating(true);
80003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
80103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
8027e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn    public void setMinTime(long minTime, WorkSource ws) {
803f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) Log.d(TAG, "setMinTime " + minTime);
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (minTime >= 0) {
80604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            mFixInterval = (int)minTime;
80704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
80804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
80904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
81004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                        mFixInterval, 0, 0)) {
81104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                    Log.e(TAG, "set_position_mode failed in setMinTime()");
81204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                }
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8173c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    public String getInternalState() {
8183c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger        return native_get_internal_state();
8193c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    }
8203c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final class Listener implements IBinder.DeathRecipient {
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IGpsStatusListener mListener;
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int mSensors = 0;
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Listener(IGpsStatusListener listener) {
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = listener;
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
831f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato            if (DEBUG) Log.d(TAG, "GPS status listener died");
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(mListeners) {
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mListeners.remove(this);
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
836fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu            if (mListener != null) {
837fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu                mListener.asBinder().unlinkToDeath(this, 0);
838fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu            }
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8422f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    public void addListener(int uid) {
84398e48691f738680fe59e7383a41458e7337daccdMike Lockwood        synchronized (mWakeLock) {
84498e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mPendingListenerMessages++;
8457e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            mWakeLock.acquire();
84698e48691f738680fe59e7383a41458e7337daccdMike Lockwood            Message m = Message.obtain(mHandler, ADD_LISTENER);
84798e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.arg1 = uid;
84898e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.sendMessage(m);
84998e48691f738680fe59e7383a41458e7337daccdMike Lockwood        }
85062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
85162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
85262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleAddListener(int uid) {
8532e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
8542e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mClientUids.indexOfKey(uid) >= 0) {
8552e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                // Shouldn't be here -- already have this uid.
8562e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                Log.w(TAG, "Duplicate add listener for uid " + uid);
8572e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                return;
8582e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            }
8592e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            mClientUids.put(uid, 0);
8602e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mNavigating) {
8612e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
8622e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    mBatteryStats.noteStartGps(uid);
8632e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
8642e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in addListener");
8652e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                }
8662f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
8672f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
8682f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
8692f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8702f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    public void removeListener(int uid) {
87198e48691f738680fe59e7383a41458e7337daccdMike Lockwood        synchronized (mWakeLock) {
87298e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mPendingListenerMessages++;
87398e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mWakeLock.acquire();
87498e48691f738680fe59e7383a41458e7337daccdMike Lockwood            Message m = Message.obtain(mHandler, REMOVE_LISTENER);
87598e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.arg1 = uid;
87698e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.sendMessage(m);
87798e48691f738680fe59e7383a41458e7337daccdMike Lockwood        }
87862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
87962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
88062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleRemoveListener(int uid) {
8812e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
8822e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mClientUids.indexOfKey(uid) < 0) {
8832e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                // Shouldn't be here -- don't have this uid.
8842e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                Log.w(TAG, "Unneeded remove listener for uid " + uid);
8852e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                return;
8862e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            }
8872e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            mClientUids.delete(uid);
8882e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mNavigating) {
8892e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
8902e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    mBatteryStats.noteStopGps(uid);
8912e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
8922e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in removeListener");
8932e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                }
8942f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
8952f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
8962f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
8972f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendExtraCommand(String command, Bundle extras) {
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
90063aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        long identity = Binder.clearCallingIdentity();
90163aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        boolean result = false;
90263aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ("delete_aiding_data".equals(command)) {
90463aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood            result = deleteAidingData(extras);
90563aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        } else if ("force_time_injection".equals(command)) {
90698e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(INJECT_NTP_TIME, 0, null);
90763aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood            result = true;
90863aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        } else if ("force_xtra_injection".equals(command)) {
9091a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood            if (mSupportsXtra) {
91093bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                xtraDownloadRequest();
91163aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood                result = true;
91293bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            }
91363aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        } else {
91463aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood            Log.w(TAG, "sendExtraCommand: unknown command " + command);
91593bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
91763aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        Binder.restoreCallingIdentity(identity);
91863aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        return result;
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean deleteAidingData(Bundle extras) {
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags;
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras == null) {
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = GPS_DELETE_ALL;
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = 0;
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (flags != 0) {
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_delete_aiding_data(flags);
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
95103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private void startNavigating(boolean singleShot) {
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStarted) {
95329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (DEBUG) Log.d(TAG, "startNavigating");
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = true;
95503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mSingleShot = singleShot;
95603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mPositionMode = GPS_POSITION_MODE_STANDALONE;
95703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
95803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood             if (Settings.Secure.getInt(mContext.getContentResolver(),
959660bbfcc54d48d5d32e64da683c76b9c372c19b1Mike Lockwood                    Settings.Secure.ASSISTED_GPS_ENABLED, 1) != 0) {
96003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                if (singleShot && hasCapability(GPS_CAPABILITY_MSA)) {
96103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    mPositionMode = GPS_POSITION_MODE_MS_ASSISTED;
9628dc16c27e23dae5bdf65fd2a2ced97c2f645a633Mike Lockwood                } else if (hasCapability(GPS_CAPABILITY_MSB)) {
96303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    mPositionMode = GPS_POSITION_MODE_MS_BASED;
96403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                }
965bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood            }
966bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood
96704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
96804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
96904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                    interval, 0, 0)) {
97004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                mStarted = false;
97104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                Log.e(TAG, "set_position_mode failed in startNavigating()");
97204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                return;
97304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            }
97404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!native_start()) {
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStarted = false;
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.e(TAG, "native_start failed in startNavigating()");
9770632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                return;
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
98115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
98229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            mFixRequestTime = System.currentTimeMillis();
98304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
98404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
98504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                // and our fix interval is not short
98604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                if (mFixInterval >= NO_FIX_TIMEOUT) {
98704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                    mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
98804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                            SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
98904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                }
9900632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            }
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
99462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void stopNavigating() {
99529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (DEBUG) Log.d(TAG, "stopNavigating");
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mStarted) {
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = false;
99803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mSingleShot = false;
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_stop();
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = 0;
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = LOCATION_INVALID;
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
100515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10090632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private void hibernate() {
10100632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        // stop GPS until our next fix interval arrives
10110632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        stopNavigating();
10120632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mTimeoutIntent);
10130632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mWakeupIntent);
10140632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        long now = SystemClock.elapsedRealtime();
10150632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
101604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                SystemClock.elapsedRealtime() + mFixInterval, mWakeupIntent);
101704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    }
101804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
101904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private boolean hasCapability(int capability) {
102004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood        return ((mEngineCapabilities & capability) != 0);
10210632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    }
10220632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our position.
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportLocation(int flags, double latitude, double longitude, double altitude,
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float speed, float bearing, float accuracy, long timestamp) {
102829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                " timestamp: " + timestamp);
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mLocation) {
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = flags;
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLatitude(latitude);
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLongitude(longitude);
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setTime(timestamp);
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAltitude(altitude);
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAltitude();
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setSpeed(speed);
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeSpeed();
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setBearing(bearing);
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeBearing();
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAccuracy(accuracy);
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAccuracy();
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
105915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            try {
1060a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                mLocationManager.reportLocation(mLocation, false);
106115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            } catch (RemoteException e) {
106215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Log.e(TAG, "RemoteException calling reportLocation");
106315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1066fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        mLastFixTime = System.currentTimeMillis();
1067fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        // report time to first fix
1068fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        if (mTTFF == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1069fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            mTTFF = (int)(mLastFixTime - mFixRequestTime);
1070f4dffd8a45386b5a5f0e6de4f30facc9eaac4001The Android Open Source Project            if (DEBUG) Log.d(TAG, "TTFF: " + mTTFF);
1071fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson
1072fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            // notify status listeners
1073fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            synchronized(mListeners) {
1074fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                int size = mListeners.size();
1075fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                for (int i = 0; i < size; i++) {
1076fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    Listener listener = mListeners.get(i);
1077fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    try {
1078f4dffd8a45386b5a5f0e6de4f30facc9eaac4001The Android Open Source Project                        listener.mListener.onFirstFix(mTTFF);
1079fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    } catch (RemoteException e) {
1080fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        Log.w(TAG, "RemoteException in stopNavigating");
1081fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        mListeners.remove(listener);
1082fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        // adjust for size of list changing
1083fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        size--;
1084fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    }
1085fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                }
1086fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            }
1087fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        }
1088fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson
108903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        if (mSingleShot) {
109003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            stopNavigating();
109103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
109215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mStarted && mStatus != LocationProvider.AVAILABLE) {
1093d53ba017ee2381383b4bb4d92e6e0e661431660fMike Lockwood            // we want to time out if we do not receive a fix
1094b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood            // within the time out and we are requesting infrequent fixes
109504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {
1096b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood                mAlarmManager.cancel(mTimeoutIntent);
1097b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood            }
1098b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is receiving fixes.
110000b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
110100b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
110315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.AVAILABLE, mSvCount);
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
110529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
110603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood       if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted && mFixInterval > 1000) {
1107d53ba017ee2381383b4bb4d92e6e0e661431660fMike Lockwood            if (DEBUG) Log.d(TAG, "got fix, hibernating");
11080632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            hibernate();
110929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        }
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   }
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our status
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportStatus(int status) {
111629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) Log.v(TAG, "reportStatus status: " + status);
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11182e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
11192e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            boolean wasNavigating = mNavigating;
1120dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood
1121cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            switch (status) {
1122cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_SESSION_BEGIN:
1123cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mNavigating = true;
1124271f9f172b241607b1ed39a7709c3ed47ee5dee7Mike Lockwood                    mEngineOn = true;
1125cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1126cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_SESSION_END:
1127cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mNavigating = false;
1128cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1129cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_ENGINE_ON:
1130cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mEngineOn = true;
1131cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1132cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_ENGINE_OFF:
1133cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mEngineOn = false;
1134271f9f172b241607b1ed39a7709c3ed47ee5dee7Mike Lockwood                    mNavigating = false;
1135cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1136cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            }
1137cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood
1138dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood            if (wasNavigating != mNavigating) {
1139dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                int size = mListeners.size();
1140dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                for (int i = 0; i < size; i++) {
1141dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    Listener listener = mListeners.get(i);
1142dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    try {
1143dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        if (mNavigating) {
1144dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            listener.mListener.onGpsStarted();
1145dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        } else {
1146dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            listener.mListener.onGpsStopped();
1147dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        }
1148dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    } catch (RemoteException e) {
1149dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        Log.w(TAG, "RemoteException in reportStatus");
1150dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        mListeners.remove(listener);
1151dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        // adjust for size of list changing
1152dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        size--;
1153dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    }
1154dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                }
1155dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood
11562e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
1157dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    // update battery stats
1158dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    for (int i=mClientUids.size() - 1; i >= 0; i--) {
1159dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        int uid = mClientUids.keyAt(i);
1160dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        if (mNavigating) {
1161dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            mBatteryStats.noteStartGps(uid);
1162dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        } else {
1163dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            mBatteryStats.noteStopGps(uid);
1164dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        }
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11662e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
11672e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in reportStatus");
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1170dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                // send an intent to notify that the GPS has been enabled or disabled.
117100b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood                Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
117200b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood                intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
1173dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                mContext.sendBroadcast(intent);
11742f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update SV info
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportSvStatus() {
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(mListeners) {
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int size = mListeners.size();
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < size; i++) {
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Listener listener = mListeners.get(i);
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs,
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSvElevations, mSvAzimuths, mSvMasks[EPHEMERIS_MASK],
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK]);
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.w(TAG, "RemoteException in reportSvInfo");
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mListeners.remove(listener);
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // adjust for size of list changing
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    size--;
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
120229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) {
120329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            Log.v(TAG, "SV count: " + svCount +
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) +
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK]));
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < svCount; i++) {
120729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                Log.v(TAG, "sv: " + mSvs[i] +
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " snr: " + (float)mSnrs[i]/10 +
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " elev: " + mSvElevations[i] +
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " azimuth: " + mSvAzimuths[i] +
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " E") +
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " A") +
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U"));
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12170881f4f9339febee85c9ab4cba69970ac5cbde55Kevin.KY Tsai        // return number of sets used in fix instead of total
12180881f4f9339febee85c9ab4cba69970ac5cbde55Kevin.KY Tsai        updateStatus(mStatus, Integer.bitCount(mSvMasks[USED_FOR_FIX_MASK]));
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
122015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
122104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is no longer receiving fixes.
122300b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
122400b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
122615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
122958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
123058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    /**
1231e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood     * called from native code to update AGPS status
123258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood     */
1233e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private void reportAGpsStatus(int type, int status) {
123458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        switch (status) {
1235e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_REQUEST_AGPS_DATA_CONN:
1236b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
12372acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                // Set mAGpsDataConnectionState before calling startUsingNetworkFeature
12382acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                //  to avoid a race condition with handleUpdateNetworkState()
12392acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
12402acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                int result = mConnMgr.startUsingNetworkFeature(
124158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                        ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
124258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                if (result == Phone.APN_ALREADY_ACTIVE) {
1243b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    if (mAGpsApn != null) {
1244b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        native_agps_data_conn_open(mAGpsApn);
1245b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
1246b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    } else {
1247b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        Log.e(TAG, "mAGpsApn not set when receiving Phone.APN_ALREADY_ACTIVE");
12482acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
1249b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        native_agps_data_conn_failed();
1250b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    }
125158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else if (result == Phone.APN_REQUEST_STARTED) {
12522acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                    // Nothing to do here
125358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else {
12542acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
1255e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_failed();
125658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
125758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1258e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_RELEASE_AGPS_DATA_CONN:
1259b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
1260e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
126158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                    mConnMgr.stopUsingNetworkFeature(
126258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                            ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
1263e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_closed();
1264e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
126558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
126658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1267e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONNECTED:
1268b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
126958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1270e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_DONE:
1271b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
127258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1273e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_FAILED:
1274b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
127558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
127658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        }
127758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    }
127858bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1279b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    /**
1280b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood     * called from native code to report NMEA data received
1281b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood     */
1282f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood    private void reportNmea(long timestamp) {
1283b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood        synchronized(mListeners) {
1284b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            int size = mListeners.size();
1285b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            if (size > 0) {
1286b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                // don't bother creating the String if we have no listeners
1287f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood                int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
1288b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                String nmea = new String(mNmeaBuffer, 0, length);
1289b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood
1290b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                for (int i = 0; i < size; i++) {
1291b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    Listener listener = mListeners.get(i);
1292b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    try {
1293b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        listener.mListener.onNmeaReceived(timestamp, nmea);
1294b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    } catch (RemoteException e) {
1295b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        Log.w(TAG, "RemoteException in reportNmea");
1296b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        mListeners.remove(listener);
1297b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        // adjust for size of list changing
1298b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        size--;
1299b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    }
1300b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                }
1301b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            }
1302b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood        }
1303b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    }
1304b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood
130562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    /**
130604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood     * called from native code to inform us what the GPS engine capabilities are
130704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood     */
130804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private void setEngineCapabilities(int capabilities) {
130904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood        mEngineCapabilities = capabilities;
131004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    }
131104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
131204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    /**
131362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood     * called from native code to request XTRA data
131462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood     */
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void xtraDownloadRequest() {
1316f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
131798e48691f738680fe59e7383a41458e7337daccdMike Lockwood        sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
132022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    //=============================================================
132122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // NI Client support
13221e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    //=============================================================
132322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
13241e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        // Sends a response for an NI reqeust to HAL.
13251e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        public boolean sendNiResponse(int notificationId, int userResponse)
13261e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        {
13271e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            // TODO Add Permission check
13281e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13291e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            StringBuilder extrasBuf = new StringBuilder();
13301e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13311e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
13321e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                    ", response: " + userResponse);
13331e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            native_send_ni_response(notificationId, userResponse);
13341e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            return true;
13351e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
133622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    };
133722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
133822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    public INetInitiatedListener getNetInitiatedListener() {
133922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        return mNetInitiatedListener;
134022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    }
134122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
134222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // Called by JNI function to report an NI request.
13431e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    public void reportNiNotification(
13441e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int notificationId,
13451e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int niType,
13461e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int notifyFlags,
13471e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int timeout,
13481e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int defaultResponse,
13491e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String requestorId,
13501e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String text,
13511e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int requestorIdEncoding,
13521e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int textEncoding,
13531e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String extras  // Encoded extra data
135422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        )
13551e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    {
13561e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Log.i(TAG, "reportNiNotification: entered");
13571e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Log.i(TAG, "notificationId: " + notificationId +
13581e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", niType: " + niType +
13591e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", notifyFlags: " + notifyFlags +
13601e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", timeout: " + timeout +
13611e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", defaultResponse: " + defaultResponse);
13621e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13631e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Log.i(TAG, "requestorId: " + requestorId +
13641e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", text: " + text +
13651e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", requestorIdEncoding: " + requestorIdEncoding +
13661e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", textEncoding: " + textEncoding);
13671e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13681e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        GpsNiNotification notification = new GpsNiNotification();
13691e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13701e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.notificationId = notificationId;
13711e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.niType = niType;
13721e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
13731e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
13741e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
13751e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.timeout = timeout;
13761e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.defaultResponse = defaultResponse;
13771e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.requestorId = requestorId;
13781e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.text = text;
13791e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.requestorIdEncoding = requestorIdEncoding;
13801e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.textEncoding = textEncoding;
13811e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13821e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        // Process extras, assuming the format is
13831e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        // one of more lines of "key = value"
13841e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Bundle bundle = new Bundle();
13851e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13861e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        if (extras == null) extras = "";
13871e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Properties extraProp = new Properties();
13881e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13891e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        try {
13901e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            extraProp.load(new StringBufferInputStream(extras));
13911e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
13921e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        catch (IOException e)
13931e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        {
13941e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
13951e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
13961e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13971e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        for (Entry<Object, Object> ent : extraProp.entrySet())
13981e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        {
13991e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            bundle.putString((String) ent.getKey(), (String) ent.getValue());
14001e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
14011e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14021e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.extras = bundle;
14031e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14041e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        mNIHandler.handleNiNotification(notification);
14051e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
14061e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14071e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    /**
14081e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * Called from native code to request set id info.
14091e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * We should be careful about receiving null string from the TelephonyManager,
14101e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * because sending null String to JNI function would cause a crash.
14111e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     */
14121e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14131e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void requestSetID(int flags) {
14141e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        TelephonyManager phone = (TelephonyManager)
14151e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                mContext.getSystemService(Context.TELEPHONY_SERVICE);
14161e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        int    type = AGPS_SETID_TYPE_NONE;
14171e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        String data = "";
14181e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14191e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
14201e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String data_temp = phone.getSubscriberId();
14211e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            if (data_temp == null) {
14221e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework does not have the SIM card ready.
14231e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else {
14241e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework has the SIM card.
14251e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                data = data_temp;
14261e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                type = AGPS_SETID_TYPE_IMSI;
14271e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            }
14281e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
14291e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
14301e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String data_temp = phone.getLine1Number();
14311e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            if (data_temp == null) {
14321e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework does not have the SIM card ready.
14331e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else {
14341e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework has the SIM card.
14351e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                data = data_temp;
14361e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                type = AGPS_SETID_TYPE_MSISDN;
14371e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            }
14381e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
14391e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        native_agps_set_id(type, data);
14401e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
14411e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14421e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    /**
14431e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * Called from native code to request reference location info
14441e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     */
14451e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14461e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void requestRefLocation(int flags) {
14471e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        TelephonyManager phone = (TelephonyManager)
14481e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                mContext.getSystemService(Context.TELEPHONY_SERVICE);
14491e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        if (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
14501e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation();
14511e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            if ((gsm_cell != null) && (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM)
14521e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                    && (phone.getNetworkOperator().length() > 3)) {
14531e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                int type;
14541e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0,3));
14551e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3));
14561e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                if (phone.getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS)
14571e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                    type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
14581e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                else
14591e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                    type = AGPS_REF_LOCATION_TYPE_GSM_CELLID;
14601e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                native_agps_set_ref_location_cellid(type, mcc, mnc,
14611e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                        gsm_cell.getLac(), gsm_cell.getCid());
14621e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            }
14631e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            else
14641e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                Log.e(TAG,"Error getting cell location info.");
14651e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
14661e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        else
14671e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            Log.e(TAG,"CDMA not supported.");
14681e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
146922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
147098e48691f738680fe59e7383a41458e7337daccdMike Lockwood    private void sendMessage(int message, int arg, Object obj) {
147198e48691f738680fe59e7383a41458e7337daccdMike Lockwood        // hold a wake lock while messages are pending
147298e48691f738680fe59e7383a41458e7337daccdMike Lockwood        synchronized (mWakeLock) {
147398e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mPendingMessageBits |= (1 << message);
147498e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mWakeLock.acquire();
147598e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.removeMessages(message);
147698e48691f738680fe59e7383a41458e7337daccdMike Lockwood            Message m = Message.obtain(mHandler, message);
147798e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.arg1 = arg;
147898e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.obj = obj;
147998e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.sendMessage(m);
148098e48691f738680fe59e7383a41458e7337daccdMike Lockwood        }
148198e48691f738680fe59e7383a41458e7337daccdMike Lockwood    }
148298e48691f738680fe59e7383a41458e7337daccdMike Lockwood
148362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private final class ProviderHandler extends Handler {
148462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        @Override
148562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        public void handleMessage(Message msg)
148662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        {
148798e48691f738680fe59e7383a41458e7337daccdMike Lockwood            int message = msg.what;
148898e48691f738680fe59e7383a41458e7337daccdMike Lockwood            switch (message) {
148962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case ENABLE:
149062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    if (msg.arg1 == 1) {
149162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                        handleEnable();
149262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    } else {
149362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                        handleDisable();
14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
149562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
149662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case ENABLE_TRACKING:
149762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleEnableLocationTracking(msg.arg1 == 1);
149862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
149903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                case REQUEST_SINGLE_SHOT:
150003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    handleRequestSingleShot();
150103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    break;
150262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case UPDATE_NETWORK_STATE:
150362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleUpdateNetworkState(msg.arg1, (NetworkInfo)msg.obj);
150462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
150562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case INJECT_NTP_TIME:
150662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleInjectNtpTime();
150762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
150862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case DOWNLOAD_XTRA_DATA:
15091a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood                    if (mSupportsXtra) {
151062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                        handleDownloadXtraData();
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
151262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
151362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case UPDATE_LOCATION:
151462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleUpdateLocation((Location)msg.obj);
151562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
151662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case ADD_LISTENER:
151762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleAddListener(msg.arg1);
151862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
151962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case REMOVE_LISTENER:
152062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleRemoveListener(msg.arg1);
152162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
152398e48691f738680fe59e7383a41458e7337daccdMike Lockwood            // release wake lock if no messages are pending
152498e48691f738680fe59e7383a41458e7337daccdMike Lockwood            synchronized (mWakeLock) {
152598e48691f738680fe59e7383a41458e7337daccdMike Lockwood                mPendingMessageBits &= ~(1 << message);
152698e48691f738680fe59e7383a41458e7337daccdMike Lockwood                if (message == ADD_LISTENER || message == REMOVE_LISTENER) {
152798e48691f738680fe59e7383a41458e7337daccdMike Lockwood                    mPendingListenerMessages--;
152898e48691f738680fe59e7383a41458e7337daccdMike Lockwood                }
152998e48691f738680fe59e7383a41458e7337daccdMike Lockwood                if (mPendingMessageBits == 0 && mPendingListenerMessages == 0) {
153098e48691f738680fe59e7383a41458e7337daccdMike Lockwood                    mWakeLock.release();
153198e48691f738680fe59e7383a41458e7337daccdMike Lockwood                }
153298e48691f738680fe59e7383a41458e7337daccdMike Lockwood            }
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
153462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    };
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
153689096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private final class GpsLocationProviderThread extends Thread {
153789096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood
153889096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        public GpsLocationProviderThread() {
153989096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            super("GpsLocationProvider");
154089096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        }
154189096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood
154289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        public void run() {
154389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
154489096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            initialize();
154589096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            Looper.prepare();
154689096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            mHandler = new ProviderHandler();
154789096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            // signal when we are initialized and ready to go
154889096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            mInitializedLatch.countDown();
154989096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            Looper.loop();
155089096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        }
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for GPS SV statistics
15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int MAX_SVS = 32;
15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int EPHEMERIS_MASK = 0;
15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int ALMANAC_MASK = 1;
15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int USED_FOR_FIX_MASK = 2;
15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // preallocated arrays, to avoid memory allocation in reportStatus()
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvs[] = new int[MAX_SVS];
15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSnrs[] = new float[MAX_SVS];
15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvElevations[] = new float[MAX_SVS];
15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvAzimuths[] = new float[MAX_SVS];
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvMasks[] = new int[3];
15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvCount;
1566b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    // preallocated to avoid memory allocation in reportNmea()
1567b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    private byte[] mNmeaBuffer = new byte[120];
15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static { class_init_native(); }
15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native void class_init_native();
15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native boolean native_is_supported();
15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_init();
15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_cleanup();
157504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private native boolean native_set_position_mode(int mode, int recurrence, int min_interval,
157604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            int preferred_accuracy, int preferred_time);
157704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private native boolean native_start();
15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_stop();
15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_delete_aiding_data(int flags);
15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // returns number of SVs
15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // mask[0] is ephemeris mask and mask[1] is almanac mask
15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native int native_read_sv_status(int[] svs, float[] snrs,
15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] elevations, float[] azimuths, int[] masks);
1584f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood    private native int native_read_nmea(byte[] buffer, int bufferSize);
1585d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood    private native void native_inject_location(double latitude, double longitude, float accuracy);
1586d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood
15873c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    // XTRA Support
15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_time(long time, long timeReference, int uncertainty);
15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_supports_xtra();
15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_xtra_data(byte[] data, int length);
1591105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
15923c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    // DEBUG Support
15933c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    private native String native_get_internal_state();
15943c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger
15953c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    // AGPS Support
1596e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_open(String apn);
1597e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_closed();
1598e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_failed();
15991e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private native void native_agps_ni_message(byte [] msg, int length);
1600a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood    private native void native_set_agps_server(int type, String hostname, int port);
160122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
160222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // Network-initiated (NI) Support
160322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private native void native_send_ni_response(int notificationId, int userResponse);
16041e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
16051e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // AGPS ril suport
16061e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
16071e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int lac, int cid);
16081e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private native void native_agps_set_id(int type, String setid);
160950130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood
161050130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood    private native void native_update_network_state(boolean connected, int type,
161150130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood            boolean roaming, String extraInfo);
16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1613