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;
20a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.app.AppOpsManager;
2129c84340a14e70419449628ab193d11b7a609e9aMike Lockwoodimport android.app.PendingIntent;
22105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.content.BroadcastReceiver;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
25105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.content.IntentFilter;
26a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tangimport android.database.Cursor;
278ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.hardware.location.GeofenceHardwareImpl;
288ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.hardware.location.IGeofenceHardware;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Criteria;
308ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport android.location.IGpsGeofenceHardware;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.IGpsStatusListener;
3215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwoodimport android.location.IGpsStatusProvider;
334e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwoodimport android.location.ILocationManager;
3422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport android.location.INetInitiatedListener;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Location;
366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.location.LocationListener;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationManager;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationProvider;
391d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnuttimport android.location.LocationRequest;
4058bda987665af759c379cd494ff4873ac61acf29Mike Lockwoodimport android.net.ConnectivityManager;
4103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwoodimport android.net.NetworkInfo;
42a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tangimport android.net.Uri;
4340e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tangimport android.os.AsyncTask;
4463aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwoodimport android.os.Binder;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
4662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwoodimport android.os.Handler;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
485cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Leaseimport android.os.Looper;
4962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwoodimport android.os.Message;
500528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwoodimport android.os.PowerManager;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
522f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport android.os.ServiceManager;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
545ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackbornimport android.os.UserHandle;
557e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackbornimport android.os.WorkSource;
56bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwoodimport android.provider.Settings;
57a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tangimport android.provider.Telephony.Carriers;
581e84da822e7aa4d494b31c8759917d2751611f84Miguel Torrojaimport android.provider.Telephony.Sms.Intents;
59b49a73dfc4c9817bba1f227e9330555acdf9b56fJake Hambyimport android.telephony.SmsMessage;
601e84da822e7aa4d494b31c8759917d2751611f84Miguel Torrojaimport android.telephony.TelephonyManager;
611e84da822e7aa4d494b31c8759917d2751611f84Miguel Torrojaimport android.telephony.gsm.GsmCellLocation;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
63104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkeyimport android.util.NtpTrustedTime;
64a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
65a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IAppOpsService;
662f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport com.android.internal.app.IBatteryStats;
6722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport com.android.internal.location.GpsNetInitiatedHandler;
686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport com.android.internal.location.ProviderProperties;
696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport com.android.internal.location.ProviderRequest;
7022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
71b49a73dfc4c9817bba1f227e9330555acdf9b56fJake Hambyimport com.android.internal.telephony.Phone;
72a639b311e93ad14d9ee5c2b2c215ed2d86c32d2aWink Savilleimport com.android.internal.telephony.PhoneConstants;
73105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport java.io.FileDescriptor;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileInputStream;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport java.io.PrintWriter;
79104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkeyimport java.io.StringReader;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
81f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwoodimport java.util.Date;
8222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport java.util.Map.Entry;
83b49a73dfc4c9817bba1f227e9330555acdf9b56fJake Hambyimport java.util.Properties;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A GPS implementation of LocationProvider used by LocationManager.
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
9089096317104722219f73a5c3cc424e6e98c90a61Mike Lockwoodpublic class GpsLocationProvider implements LocationProviderInterface {
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "GpsLocationProvider";
9329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
941715cb36d9231f08f244ec6c0a373f1a46d66cc7Brian Muramatsu    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
951715cb36d9231f08f244ec6c0a373f1a46d66cc7Brian Muramatsu    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
9662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final ProviderProperties PROPERTIES = new ProviderProperties(
986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            true, true, false, false, true, true, true,
996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
1006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
101105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    // these need to match GpsPositionMode enum in gps.h
102105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_STANDALONE = 0;
103105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_MS_BASED = 1;
104105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
105105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
10604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // these need to match GpsPositionRecurrence enum in gps.h
10704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_POSITION_RECURRENCE_PERIODIC = 0;
10804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_POSITION_RECURRENCE_SINGLE = 1;
10904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these need to match GpsStatusValue defines in gps.h
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_NONE = 0;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_SESSION_BEGIN = 1;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_SESSION_END = 2;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_ENGINE_ON = 3;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_ENGINE_OFF = 4;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
117e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // these need to match GpsApgsStatusValue defines in gps.h
118e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    /** AGPS status event values. */
119e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
120e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
121e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONNECTED = 3;
122e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONN_DONE = 4;
123e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
12458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these need to match GpsLocationFlags enum in gps.h
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_INVALID = 0;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_LAT_LONG = 1;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_ALTITUDE = 2;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_SPEED = 4;
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_BEARING = 8;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_ACCURACY = 16;
132e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
133e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood// IMPORTANT - the GPS_DELETE_* symbols here must match constants in gps.h
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_EPHEMERIS = 0x0001;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_ALMANAC = 0x0002;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_POSITION = 0x0004;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_TIME = 0x0008;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_IONO = 0x0010;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_UTC = 0x0020;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_HEALTH = 0x0040;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SVDIR = 0x0080;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SVSTEER = 0x0100;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SADATA = 0x0200;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_RTI = 0x0400;
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_ALL = 0xFFFF;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // The GPS_CAPABILITY_* flags must match the values in gps.h
14904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_SCHEDULING = 0x0000001;
15004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_MSB = 0x0000002;
15104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_MSA = 0x0000004;
15204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
1539b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010;
15404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
155e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // these need to match AGpsType enum in gps.h
156e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_TYPE_SUPL = 1;
157e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_TYPE_C2K = 2;
158e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
159e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // for mAGpsDataConnectionState
160e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
161e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_OPENING = 1;
162e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_OPEN = 2;
16358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
16462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    // Handler messages
16562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int CHECK_LOCATION = 1;
16662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int ENABLE = 2;
1676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final int SET_REQUEST = 3;
16862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int UPDATE_NETWORK_STATE = 4;
16962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int INJECT_NTP_TIME = 5;
17062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int DOWNLOAD_XTRA_DATA = 6;
17162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int UPDATE_LOCATION = 7;
17262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int ADD_LISTENER = 8;
17362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int REMOVE_LISTENER = 9;
17440e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang    private static final int INJECT_NTP_TIME_FINISHED = 10;
17540e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang    private static final int DOWNLOAD_XTRA_DATA_FINISHED = 11;
17662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
1771e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // Request setid
1781e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
1791e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2;
1801e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
1811e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // Request ref location
1821e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_RIL_REQUEST_REFLOC_CELLID = 1;
1831e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_RIL_REQUEST_REFLOC_MAC = 2;
1841e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
1851e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // ref. location info
1861e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
1871e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
1881e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_REG_LOCATION_TYPE_MAC        = 3;
1891e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
1901e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // set id info
1911e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_SETID_TYPE_NONE = 0;
1921e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_SETID_TYPE_IMSI = 1;
1931e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_SETID_TYPE_MSISDN = 2;
1941e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String PROPERTIES_FILE = "/etc/gps.conf";
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    /** simpler wrapper for ProviderRequest + Worksource */
1986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static class GpsRequest {
1996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        public ProviderRequest request;
2006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        public WorkSource source;
2016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        public GpsRequest(ProviderRequest request, WorkSource source) {
2026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            this.request = request;
2036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            this.source = source;
2046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
2056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
2066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private Object mLock = new Object();
2086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mLocationFlags = LOCATION_INVALID;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current status
21215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time for last status update
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mStatusUpdateTime = SystemClock.elapsedRealtime();
216d53ba017ee2381383b4bb4d92e6e0e661431660fMike Lockwood
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // turn off GPS fix icon if we haven't received a fix in 10 seconds
21804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final long RECENT_FIX_TIMEOUT = 10 * 1000;
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2200632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    // stop trying if we do not receive a fix within 60 seconds
22104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int NO_FIX_TIMEOUT = 60 * 1000;
2220632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
223b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly    // if the fix interval is below this we leave GPS on,
224b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly    // if above then we cycle the GPS driver.
225b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly    // Typical hot TTTF is ~5 seconds, so 10 seconds seems sane.
226b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly    private static final int GPS_POLLING_THRESHOLD_INTERVAL = 10 * 1000;
227b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly
2286fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // how often to request NTP time, in milliseconds
2296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // current setting 24 hours
2306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final long NTP_INTERVAL = 24*60*60*1000;
2316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // how long to wait if we have a network error in NTP or XTRA downloading
2326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // current setting - 5 minutes
2336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final long RETRY_INTERVAL = 5*60*1000;
2346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // true if we are enabled, protected by this
2366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private boolean mEnabled;
2376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we have network connectivity
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNetworkAvailable;
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24140e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang    // states for injecting ntp and downloading xtra data
24240e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang    private static final int STATE_PENDING_NETWORK = 0;
24340e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang    private static final int STATE_DOWNLOADING = 1;
24440e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang    private static final int STATE_IDLE = 2;
24540e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang
24662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    // flags to trigger NTP or XTRA data download when network becomes available
24762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    // initialized to true so we do NTP and XTRA when the network comes up after booting
24840e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang    private int mInjectNtpTimePending = STATE_PENDING_NETWORK;
24940e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang    private int mDownloadXtraDataPending = STATE_PENDING_NETWORK;
25062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
2519b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    // set to true if the GPS engine does not do on-demand NTP time requests
2529b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    private boolean mPeriodicTimeInjection;
2539b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if GPS is navigating
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNavigating;
256cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood
257cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood    // true if GPS engine is on
258cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood    private boolean mEngineOn;
2596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
26004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // requested frequency of fixes, in milliseconds
26104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private int mFixInterval = 1000;
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we started navigation
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mStarted;
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2661d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt    // true if single shot request is in progress
2671d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt    private boolean mSingleShot;
2681d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt
26904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // capabilities of the GPS engine
27004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private int mEngineCapabilities;
27104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
2721a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood    // true if XTRA is supported
2731a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood    private boolean mSupportsXtra;
2741a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for calculating time to first fix
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mFixRequestTime = 0;
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time to first fix for most recent session
2786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private int mTimeToFirstFix = 0;
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time we received our last fix
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mLastFixTime;
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
28204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private int mPositionMode;
28304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // properties loaded from PROPERTIES_FILE
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Properties mProperties;
286734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private String mSuplServerHost;
287734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private int mSuplServerPort;
288734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private String mC2KServerHost;
289734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private int mC2KServerPort;
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
29115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final Context mContext;
292104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey    private final NtpTrustedTime mNtpTime;
2936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final ILocationManager mILocationManager;
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Bundle mLocationExtras = new Bundle();
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<Listener> mListeners = new ArrayList<Listener>();
29762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
2985c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease    // Handler for processing events
29962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private Handler mHandler;
300105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
301e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private String mAGpsApn;
302e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private int mAGpsDataConnectionState;
3038efd74dbedb65f69734318d9d6be70767f30b57aStephen Li    private int mAGpsDataConnectionIpAddr;
3042f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final ConnectivityManager mConnMgr;
3056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final GpsNetInitiatedHandler mNIHandler;
3062f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
3070528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    // Wakelocks
3080528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final static String WAKELOCK_KEY = "GpsLocationProvider";
3090528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final PowerManager.WakeLock mWakeLock;
3100528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
31129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    // Alarms
31229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
3130632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
31429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final AlarmManager mAlarmManager;
31529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final PendingIntent mWakeupIntent;
3160632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final PendingIntent mTimeoutIntent;
31729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
318a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private final IAppOpsService mAppOpsService;
3192f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final IBatteryStats mBatteryStats;
320105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
3216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // only modified on handler thread
322002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn    private WorkSource mClientSource = new WorkSource();
323f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood
3248ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private GeofenceHardwareImpl mGeofenceHardwareImpl;
3258ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
32615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
3276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        @Override
32815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
32915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
33015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
33115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
33215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
3336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            synchronized (mListeners) {
33415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
33515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
33615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size; i++) {
33715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
33815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
33915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        // listener already added
34015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        return;
34115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
34215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
34315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
34415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = new Listener(listener);
34515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                binder.linkToDeath(l, 0);
34615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                mListeners.add(l);
34715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
34815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
34915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
3506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        @Override
35115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void removeGpsStatusListener(IGpsStatusListener listener) {
35215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
35315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
35415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
35515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
3566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            synchronized (mListeners) {
35715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
35815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = null;
35915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
36015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size && l == null; i++) {
36115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
36215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
36315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        l = test;
36415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
36515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
36615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
36715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                if (l != null) {
36815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    mListeners.remove(l);
36915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    binder.unlinkToDeath(l, 0);
37015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
37115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
37215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
37315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    };
37415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
37515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    public IGpsStatusProvider getGpsStatusProvider() {
37615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        return mGpsStatusProvider;
37715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
37815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
3798ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    public IGpsGeofenceHardware getGpsGeofenceProxy() {
3808ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        return mGpsGeofenceBinder;
3818ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
3828ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
38329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
384105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        @Override public void onReceive(Context context, Intent intent) {
385105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            String action = intent.getAction();
386105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
38729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (action.equals(ALARM_WAKEUP)) {
38829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_WAKEUP");
3891d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                startNavigating(false);
3900632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            } else if (action.equals(ALARM_TIMEOUT)) {
3910632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");
3920632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                hibernate();
3931e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {
3941e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                checkSmsSuplInit(intent);
3951e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
3961e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                checkWapSuplInit(intent);
3976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly             } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
3986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                 int networkState;
3996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                 if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false)) {
4006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                     networkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
4016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                 } else {
4026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                     networkState = LocationProvider.AVAILABLE;
4036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                 }
4046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
4056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                 // retrieve NetworkInfo result for this UID
4066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                 NetworkInfo info =
4076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                         intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
4086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                 ConnectivityManager connManager = (ConnectivityManager)
4096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                         mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
4106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                 info = connManager.getNetworkInfo(info.getType());
4116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
4126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                 updateNetworkState(networkState, info);
4131e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja             }
414105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
41529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    };
416105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
4171e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void checkSmsSuplInit(Intent intent) {
4181e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        SmsMessage[] messages = Intents.getMessagesFromIntent(intent);
4191e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        for (int i=0; i <messages.length; i++) {
4201e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            byte[] supl_init = messages[i].getUserData();
4211e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            native_agps_ni_message(supl_init,supl_init.length);
4221e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
4231e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
4241e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
4251e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void checkWapSuplInit(Intent intent) {
4261e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        byte[] supl_init = (byte[]) intent.getExtra("data");
4271e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        native_agps_ni_message(supl_init,supl_init.length);
4281e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
4291e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean isSupported() {
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_is_supported();
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4345cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease    public GpsLocationProvider(Context context, ILocationManager ilocationManager,
4355cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease            Looper looper) {
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
437104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey        mNtpTime = NtpTrustedTime.getInstance(context);
4386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mILocationManager = ilocationManager;
43979e642e8ed75033eacc461633a8f4cd5157d25dfMike Lockwood        mNIHandler = new GpsNetInitiatedHandler(context);
44063598a0619776b421f27cd12fb29eb83dc327997Mike Lockwood
44163598a0619776b421f27cd12fb29eb83dc327997Mike Lockwood        mLocation.setExtras(mLocationExtras);
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4430528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // Create a wake lock
4440528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
4450528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
4466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mWakeLock.setReferenceCounted(true);
4470528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
44829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
44929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
4500632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
45129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
45258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
45358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
454a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        // App ops service to keep track of who is accessing the GPS
455a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(
456a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                Context.APP_OPS_SERVICE));
457a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
4582f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        // Battery statistics service to be notified when GPS turns on or off
4592f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
4602f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProperties = new Properties();
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            File file = new File(PROPERTIES_FILE);
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            FileInputStream stream = new FileInputStream(file);
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProperties.load(stream);
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stream.close();
467e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
468734d6031a662a275ec68627bd1258159041d44deMike Lockwood            mSuplServerHost = mProperties.getProperty("SUPL_HOST");
469e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            String portString = mProperties.getProperty("SUPL_PORT");
470734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mSuplServerHost != null && portString != null) {
471105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                try {
472734d6031a662a275ec68627bd1258159041d44deMike Lockwood                    mSuplServerPort = Integer.parseInt(portString);
473105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                } catch (NumberFormatException e) {
474e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
475e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                }
476e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            }
477e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
478734d6031a662a275ec68627bd1258159041d44deMike Lockwood            mC2KServerHost = mProperties.getProperty("C2K_HOST");
479e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            portString = mProperties.getProperty("C2K_PORT");
480734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mC2KServerHost != null && portString != null) {
481e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                try {
482734d6031a662a275ec68627bd1258159041d44deMike Lockwood                    mC2KServerPort = Integer.parseInt(portString);
483e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                } catch (NumberFormatException e) {
484e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse C2K_PORT: " + portString);
485105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                }
486105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
49062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
4915c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        // construct handler, listen for events
4925cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease        mHandler = new ProviderHandler(looper);
4935c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        listenForBroadcasts();
4945c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease
4955c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        // also listen for PASSIVE_PROVIDER updates
4965c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        mHandler.post(new Runnable() {
4975c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease            @Override
4985c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease            public void run() {
4995c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease                LocationManager locManager =
5005c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease                        (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
5015c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease                locManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER,
5025c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease                        0, 0, new NetworkLocationListener(), mHandler.getLooper());
50389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            }
5045c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        });
50562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
50662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
5075c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease    private void listenForBroadcasts() {
50862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        IntentFilter intentFilter = new IntentFilter();
5095c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
5105c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        intentFilter.addDataScheme("sms");
5115c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        intentFilter.addDataAuthority("localhost","7275");
5125c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        mContext.registerReceiver(mBroadcastReciever, intentFilter, null, mHandler);
5135c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease
5145c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        intentFilter = new IntentFilter();
5155c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
5165c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        try {
5175c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease            intentFilter.addDataType("application/vnd.omaloc-supl-init");
5185c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        } catch (IntentFilter.MalformedMimeTypeException e) {
5195c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease            Log.w(TAG, "Malformed SUPL init mime type");
5205c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        }
5215c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        mContext.registerReceiver(mBroadcastReciever, intentFilter, null, mHandler);
5225c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease
5235c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        intentFilter = new IntentFilter();
52462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        intentFilter.addAction(ALARM_WAKEUP);
52562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        intentFilter.addAction(ALARM_TIMEOUT);
526b94b41f516e69e137553157064f9619e1a2188e3Brian Muramatsu        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
5275c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        mContext.registerReceiver(mBroadcastReciever, intentFilter, null, mHandler);
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
531d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood     * Returns the name of this provider.
532d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood     */
5336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
534d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    public String getName() {
535d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        return LocationManager.GPS_PROVIDER;
536d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    }
537d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood
5386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
5396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public ProviderProperties getProperties() {
5406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        return PROPERTIES;
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
54303d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood    public void updateNetworkState(int state, NetworkInfo info) {
54498e48691f738680fe59e7383a41458e7337daccdMike Lockwood        sendMessage(UPDATE_NETWORK_STATE, state, info);
54562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
54662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
54762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleUpdateNetworkState(int state, NetworkInfo info) {
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNetworkAvailable = (state == LocationProvider.AVAILABLE);
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
550f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) {
55103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            Log.d(TAG, "updateNetworkState " + (mNetworkAvailable ? "available" : "unavailable")
55203d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                + " info: " + info);
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
55403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood
55550130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood        if (info != null) {
556bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown            boolean dataEnabled = Settings.Global.getInt(mContext.getContentResolver(),
557bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown                                                         Settings.Global.MOBILE_DATA, 1) == 1;
558a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            boolean networkAvailable = info.isAvailable() && dataEnabled;
559a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            String defaultApn = getSelectedApn();
560a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            if (defaultApn == null) {
561a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                defaultApn = "dummy-apn";
562a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            }
563a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang
56450130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood            native_update_network_state(info.isConnected(), info.getType(),
565a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                                        info.isRoaming(), networkAvailable,
566a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                                        info.getExtraInfo(), defaultApn);
56750130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood        }
56850130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood
56903d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood        if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL
57003d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
57103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            String apnName = info.getExtraInfo();
57283b69713f2dbeee7ff5e07836673a9a477be236fStephen Li            if (mNetworkAvailable) {
57383b69713f2dbeee7ff5e07836673a9a477be236fStephen Li                if (apnName == null) {
5746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    /* Assign a dummy value in the case of C2K as otherwise we will have a runtime
57583b69713f2dbeee7ff5e07836673a9a477be236fStephen Li                    exception in the following call to native_agps_data_conn_open*/
57683b69713f2dbeee7ff5e07836673a9a477be236fStephen Li                    apnName = "dummy-apn";
57783b69713f2dbeee7ff5e07836673a9a477be236fStephen Li                }
57803d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsApn = apnName;
5798efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                if (DEBUG) Log.d(TAG, "mAGpsDataConnectionIpAddr " + mAGpsDataConnectionIpAddr);
5808efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                if (mAGpsDataConnectionIpAddr != 0xffffffff) {
5818efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                    boolean route_result;
5828efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                    if (DEBUG) Log.d(TAG, "call requestRouteToHost");
5838efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                    route_result = mConnMgr.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_SUPL,
5848efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                        mAGpsDataConnectionIpAddr);
5858efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                    if (route_result == false) Log.d(TAG, "call requestRouteToHost failed");
5868efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                }
58703d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                if (DEBUG) Log.d(TAG, "call native_agps_data_conn_open");
58803d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                native_agps_data_conn_open(apnName);
58903d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
59003d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            } else {
59103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                if (DEBUG) Log.d(TAG, "call native_agps_data_conn_failed");
59203d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsApn = null;
59303d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
59403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                native_agps_data_conn_failed();
59503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            }
59603d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood        }
59703d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood
59862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (mNetworkAvailable) {
59940e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang            if (mInjectNtpTimePending == STATE_PENDING_NETWORK) {
60098e48691f738680fe59e7383a41458e7337daccdMike Lockwood                sendMessage(INJECT_NTP_TIME, 0, null);
60162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            }
60240e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang            if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
60398e48691f738680fe59e7383a41458e7337daccdMike Lockwood                sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
60462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            }
60562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
60662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
60762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
60862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleInjectNtpTime() {
60940e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang        if (mInjectNtpTimePending == STATE_DOWNLOADING) {
61040e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang            // already downloading data
61140e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang            return;
61240e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang        }
61362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (!mNetworkAvailable) {
61462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            // try again when network is up
61540e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang            mInjectNtpTimePending = STATE_PENDING_NETWORK;
61662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            return;
61762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
61840e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang        mInjectNtpTimePending = STATE_DOWNLOADING;
61962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
620028872fe07f9b3468aa1506c658d6aae25f53015Jeff Brown        // hold wake lock while task runs
621028872fe07f9b3468aa1506c658d6aae25f53015Jeff Brown        mWakeLock.acquire();
62240e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang        AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
62340e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang            @Override
62440e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang            public void run() {
62540e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                long delay;
62662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
62740e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                // force refresh NTP cache when outdated
62840e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
62940e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    mNtpTime.forceRefresh();
63040e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                }
631104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey
63240e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                // only update when NTP time is fresh
63340e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
63440e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    long time = mNtpTime.getCachedNtpTime();
63540e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    long timeReference = mNtpTime.getCachedNtpTimeReference();
63640e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    long certainty = mNtpTime.getCacheCertainty();
63740e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    long now = System.currentTimeMillis();
63840e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang
63940e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    Log.d(TAG, "NTP server returned: "
64040e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                            + time + " (" + new Date(time)
64140e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                            + ") reference: " + timeReference
64240e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                            + " certainty: " + certainty
64340e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                            + " system time offset: " + (time - now));
64440e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang
64540e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    native_inject_time(time, timeReference, (int) certainty);
64640e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    delay = NTP_INTERVAL;
64740e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                } else {
64840e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    if (DEBUG) Log.d(TAG, "requestTime failed");
64940e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    delay = RETRY_INTERVAL;
65040e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                }
65162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
652028872fe07f9b3468aa1506c658d6aae25f53015Jeff Brown                sendMessage(INJECT_NTP_TIME_FINISHED, 0, null);
65340e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang
65440e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                if (mPeriodicTimeInjection) {
65540e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    // send delayed message for next NTP injection
65640e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    // since this is delayed and not urgent we do not hold a wake lock here
657028872fe07f9b3468aa1506c658d6aae25f53015Jeff Brown                    mHandler.sendEmptyMessageDelayed(INJECT_NTP_TIME, delay);
65840e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                }
659028872fe07f9b3468aa1506c658d6aae25f53015Jeff Brown
660028872fe07f9b3468aa1506c658d6aae25f53015Jeff Brown                // release wake lock held by task
661028872fe07f9b3468aa1506c658d6aae25f53015Jeff Brown                mWakeLock.release();
66240e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang            }
66340e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang        });
66462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
66562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
66662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleDownloadXtraData() {
66740e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang        if (mDownloadXtraDataPending == STATE_DOWNLOADING) {
66840e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang            // already downloading data
66940e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang            return;
67040e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang        }
6715723dfe8c87d0887b8926f43637ed300466890d2Mike Lockwood        if (!mNetworkAvailable) {
67262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            // try again when network is up
67340e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang            mDownloadXtraDataPending = STATE_PENDING_NETWORK;
67462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            return;
67562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
67640e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang        mDownloadXtraDataPending = STATE_DOWNLOADING;
67740e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang
678028872fe07f9b3468aa1506c658d6aae25f53015Jeff Brown        // hold wake lock while task runs
679028872fe07f9b3468aa1506c658d6aae25f53015Jeff Brown        mWakeLock.acquire();
68040e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang        AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
68140e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang            @Override
68240e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang            public void run() {
68340e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
68440e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                byte[] data = xtraDownloader.downloadXtraData();
68540e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                if (data != null) {
68640e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    if (DEBUG) {
68740e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                        Log.d(TAG, "calling native_inject_xtra_data");
68840e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    }
68940e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    native_inject_xtra_data(data, data.length);
69040e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                }
69162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
692028872fe07f9b3468aa1506c658d6aae25f53015Jeff Brown                sendMessage(DOWNLOAD_XTRA_DATA_FINISHED, 0, null);
69362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
69440e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                if (data == null) {
69540e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    // try again later
69640e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    // since this is delayed and not urgent we do not hold a wake lock here
697028872fe07f9b3468aa1506c658d6aae25f53015Jeff Brown                    mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA, RETRY_INTERVAL);
69840e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                }
69940e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang
700028872fe07f9b3468aa1506c658d6aae25f53015Jeff Brown                // release wake lock held by task
701028872fe07f9b3468aa1506c658d6aae25f53015Jeff Brown                mWakeLock.release();
702028872fe07f9b3468aa1506c658d6aae25f53015Jeff Brown            }
70340e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang        });
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
70662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleUpdateLocation(Location location) {
707d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        if (location.hasAccuracy()) {
708d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood            native_inject_location(location.getLatitude(), location.getLongitude(),
709d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood                    location.getAccuracy());
710d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        }
711fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    }
712fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood
713fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    /**
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Enables this provider.  When enabled, calls to getStatus()
7154e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * must be handled.  Hardware may be started up
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the provider is enabled.
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
71962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    public void enable() {
7207b5aeca50b3069b1f8bd4db0317a3829c4b540a2Laurent Tu        synchronized (mLock) {
7217b5aeca50b3069b1f8bd4db0317a3829c4b540a2Laurent Tu            if (mEnabled) return;
7227b5aeca50b3069b1f8bd4db0317a3829c4b540a2Laurent Tu            mEnabled = true;
7237b5aeca50b3069b1f8bd4db0317a3829c4b540a2Laurent Tu        }
7247b5aeca50b3069b1f8bd4db0317a3829c4b540a2Laurent Tu
7256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        sendMessage(ENABLE, 1, null);
72662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
72762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
72862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleEnable() {
72962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (DEBUG) Log.d(TAG, "handleEnable");
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        boolean enabled = native_init();
7326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
7336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (enabled) {
7341a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood            mSupportsXtra = native_supports_xtra();
735734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mSuplServerHost != null) {
736734d6031a662a275ec68627bd1258159041d44deMike Lockwood                native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
737734d6031a662a275ec68627bd1258159041d44deMike Lockwood            }
738734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mC2KServerHost != null) {
739734d6031a662a275ec68627bd1258159041d44deMike Lockwood                native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
740734d6031a662a275ec68627bd1258159041d44deMike Lockwood            }
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            synchronized (mLock) {
7436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                mEnabled = false;
7446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Failed to enable location provider");
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Disables this provider.  When disabled, calls to getStatus()
7514e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * need not be handled.  Hardware may be shut
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * down while the provider is disabled.
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
75562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    public void disable() {
7567b5aeca50b3069b1f8bd4db0317a3829c4b540a2Laurent Tu        synchronized (mLock) {
7577b5aeca50b3069b1f8bd4db0317a3829c4b540a2Laurent Tu            if (!mEnabled) return;
7587b5aeca50b3069b1f8bd4db0317a3829c4b540a2Laurent Tu            mEnabled = false;
7597b5aeca50b3069b1f8bd4db0317a3829c4b540a2Laurent Tu        }
7607b5aeca50b3069b1f8bd4db0317a3829c4b540a2Laurent Tu
7616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        sendMessage(ENABLE, 0, null);
76262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
76362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
76462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleDisable() {
76589096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        if (DEBUG) Log.d(TAG, "handleDisable");
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        stopNavigating();
7686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mAlarmManager.cancel(mWakeupIntent);
7696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mAlarmManager.cancel(mTimeoutIntent);
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
771cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood        // do this before releasing wakelock
772cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood        native_cleanup();
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
776d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    public boolean isEnabled() {
7776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        synchronized (mLock) {
7786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return mEnabled;
7796fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
780d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    }
781d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood
7826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getStatus(Bundle extras) {
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras != null) {
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            extras.putInt("satellites", mSvCount);
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatus;
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateStatus(int status, int svCount) {
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (status != mStatus || svCount != mSvCount) {
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatus = status;
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSvCount = svCount;
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationExtras.putInt("satellites", svCount);
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatusUpdateTime = SystemClock.elapsedRealtime();
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public long getStatusUpdateTime() {
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatusUpdateTime;
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
8056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void setRequest(ProviderRequest request, WorkSource source) {
8066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        sendMessage(SET_REQUEST, 0, new GpsRequest(request, source));
80762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
80862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
8096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void handleSetRequest(ProviderRequest request, WorkSource source) {
8101d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt        boolean singleShot = false;
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8121d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt        // see if the request is for a single update
8131d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt        if (request.locationRequests != null && request.locationRequests.size() > 0) {
8141d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt            // if any request has zero or more than one updates
8151d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt            // requested, then this is not single-shot mode
8161d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt            singleShot = true;
81703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
8181d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt            for (LocationRequest lr : request.locationRequests) {
8191d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                if (lr.getNumUpdates() != 1) {
8201d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                    singleShot = false;
8211d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                }
8221d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt            }
8231d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt        }
82403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
8251d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt        if (DEBUG) Log.d(TAG, "setRequest " + request);
8266fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (request.reportLocation) {
8276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // update client uids
828002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn            updateClientUids(source);
82904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
8306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mFixInterval = (int) request.interval;
8316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
8326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // check for overflow
8336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (mFixInterval != request.interval) {
8346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                Log.w(TAG, "interval overflow: " + request.interval);
8356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                mFixInterval = Integer.MAX_VALUE;
8366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
8376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
8386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // apply request to GPS engine
83904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
8406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // change period
84104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
84204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                        mFixInterval, 0, 0)) {
84304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                    Log.e(TAG, "set_position_mode failed in setMinTime()");
84404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                }
8456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            } else if (!mStarted) {
8466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // start GPS
8471d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                startNavigating(singleShot);
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else {
850002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn            updateClientUids(new WorkSource());
851b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly
8526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            stopNavigating();
8536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mAlarmManager.cancel(mWakeupIntent);
8546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mAlarmManager.cancel(mTimeoutIntent);
8556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
8563c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    }
8573c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final class Listener implements IBinder.DeathRecipient {
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IGpsStatusListener mListener;
8606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Listener(IGpsStatusListener listener) {
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = listener;
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
8656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        @Override
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
867f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato            if (DEBUG) Log.d(TAG, "GPS status listener died");
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            synchronized (mListeners) {
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mListeners.remove(this);
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
872fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu            if (mListener != null) {
873fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu                mListener.asBinder().unlinkToDeath(this, 0);
874fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu            }
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
878002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn    private void updateClientUids(WorkSource source) {
879002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn        // Update work source.
880002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn        WorkSource[] changes = mClientSource.setReturningDiffs(source);
881ea78b85bb7b688a513fcf456f0e1aeee11e106eaVictoria Lease        if (changes == null) {
882ea78b85bb7b688a513fcf456f0e1aeee11e106eaVictoria Lease            return;
883ea78b85bb7b688a513fcf456f0e1aeee11e106eaVictoria Lease        }
884002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn        WorkSource newWork = changes[0];
885002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn        WorkSource goneWork = changes[1];
886002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn
887002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn        // Update sources that were not previously tracked.
888002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn        if (newWork != null) {
889002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn            int lastuid = -1;
890002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn            for (int i=0; i<newWork.size(); i++) {
8912e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
892002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                    int uid = newWork.get(i);
893002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                    mAppOpsService.startOperation(AppOpsManager.OP_GPS, uid, newWork.getName(i));
894002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                    if (uid != lastuid) {
895002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                        lastuid = uid;
896002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                        mBatteryStats.noteStartGps(uid);
897002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                    }
8982e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
8996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    Log.w(TAG, "RemoteException", e);
9002e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                }
9012f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
9022f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
90362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
904002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn        // Update sources that are no longer tracked.
905002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn        if (goneWork != null) {
906002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn            int lastuid = -1;
907002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn            for (int i=0; i<goneWork.size(); i++) {
9082e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
909002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                    int uid = goneWork.get(i);
910002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                    mAppOpsService.finishOperation(AppOpsManager.OP_GPS, uid, goneWork.getName(i));
911002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                    if (uid != lastuid) {
912002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                        lastuid = uid;
913002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                        mBatteryStats.noteStopGps(uid);
914002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                    }
9152e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
9166fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    Log.w(TAG, "RemoteException", e);
9172e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                }
9182f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
9192f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
9202f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
9212f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
9226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendExtraCommand(String command, Bundle extras) {
9246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
92563aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        long identity = Binder.clearCallingIdentity();
92663aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        boolean result = false;
92763aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ("delete_aiding_data".equals(command)) {
92963aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood            result = deleteAidingData(extras);
93063aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        } else if ("force_time_injection".equals(command)) {
93198e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(INJECT_NTP_TIME, 0, null);
93263aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood            result = true;
93363aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        } else if ("force_xtra_injection".equals(command)) {
9341a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood            if (mSupportsXtra) {
93593bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                xtraDownloadRequest();
93663aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood                result = true;
93793bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            }
93863aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        } else {
93963aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood            Log.w(TAG, "sendExtraCommand: unknown command " + command);
94093bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
9416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
94263aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        Binder.restoreCallingIdentity(identity);
94363aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        return result;
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9468ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private IGpsGeofenceHardware mGpsGeofenceBinder = new IGpsGeofenceHardware.Stub() {
9478ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        public boolean isHardwareGeofenceSupported() {
9488ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            return native_is_geofence_supported();
9498ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
9508ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
9518ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        public boolean addCircularHardwareGeofence(int geofenceId, double latitude,
9528ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                double longitude, double radius, int lastTransition, int monitorTransitions,
9538ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                int notificationResponsiveness, int unknownTimer) {
9548ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            return native_add_geofence(geofenceId, latitude, longitude, radius,
9558ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                    lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer);
9568ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
9578ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
9588ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        public boolean removeHardwareGeofence(int geofenceId) {
9598ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            return native_remove_geofence(geofenceId);
9608ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
9618ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
9628ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        public boolean pauseHardwareGeofence(int geofenceId) {
9638ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            return native_pause_geofence(geofenceId);
9648ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
9658ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
9668ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        public boolean resumeHardwareGeofence(int geofenceId, int monitorTransition) {
9678ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            return native_resume_geofence(geofenceId, monitorTransition);
9688ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
9698ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    };
9708ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean deleteAidingData(Bundle extras) {
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags;
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras == null) {
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = GPS_DELETE_ALL;
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = 0;
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (flags != 0) {
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_delete_aiding_data(flags);
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10011d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt    private void startNavigating(boolean singleShot) {
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStarted) {
10031d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt            if (DEBUG) Log.d(TAG, "startNavigating, singleShot is " + singleShot);
10046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mTimeToFirstFix = 0;
10056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mLastFixTime = 0;
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = true;
10071d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt            mSingleShot = singleShot;
100803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mPositionMode = GPS_POSITION_MODE_STANDALONE;
100903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
1010bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown             if (Settings.Global.getInt(mContext.getContentResolver(),
1011bf6f6f9de72c9fd15e6bda9f228c05a9b37d6324Jeff Brown                    Settings.Global.ASSISTED_GPS_ENABLED, 1) != 0) {
10121d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                if (singleShot && hasCapability(GPS_CAPABILITY_MSA)) {
10131d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                    mPositionMode = GPS_POSITION_MODE_MS_ASSISTED;
10141d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                } else if (hasCapability(GPS_CAPABILITY_MSB)) {
101503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    mPositionMode = GPS_POSITION_MODE_MS_BASED;
101603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                }
1017bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood            }
1018bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood
10191d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt            if (DEBUG) {
10201d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                String mode;
10211d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt
10221d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                switch(mPositionMode) {
10231d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                    case GPS_POSITION_MODE_STANDALONE:
10241d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                        mode = "standalone";
10251d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                        break;
10261d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                    case GPS_POSITION_MODE_MS_ASSISTED:
10271d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                        mode = "MS_ASSISTED";
10281d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                        break;
10291d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                    case GPS_POSITION_MODE_MS_BASED:
10301d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                        mode = "MS_BASED";
10311d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                        break;
10321d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                    default:
10331d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                        mode = "unknown";
10341d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                        break;
10351d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                }
10361d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                Log.d(TAG, "setting position_mode to " + mode);
10371d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt            }
10381d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt
103904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
104004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
104104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                    interval, 0, 0)) {
104204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                mStarted = false;
104304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                Log.e(TAG, "set_position_mode failed in startNavigating()");
104404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                return;
104504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            }
104604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!native_start()) {
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStarted = false;
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.e(TAG, "native_start failed in startNavigating()");
10490632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                return;
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
105315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
105429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            mFixRequestTime = System.currentTimeMillis();
105504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
105604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
105704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                // and our fix interval is not short
105804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                if (mFixInterval >= NO_FIX_TIMEOUT) {
105904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                    mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
106004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                            SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
106104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                }
10620632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            }
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
106662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void stopNavigating() {
106729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (DEBUG) Log.d(TAG, "stopNavigating");
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mStarted) {
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = false;
10701d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt            mSingleShot = false;
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_stop();
10726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mTimeToFirstFix = 0;
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = LOCATION_INVALID;
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
107715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10810632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private void hibernate() {
10820632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        // stop GPS until our next fix interval arrives
10830632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        stopNavigating();
10840632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mTimeoutIntent);
10850632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mWakeupIntent);
10860632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        long now = SystemClock.elapsedRealtime();
10876fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, mWakeupIntent);
108804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    }
108904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
109004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private boolean hasCapability(int capability) {
109104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood        return ((mEngineCapabilities & capability) != 0);
10920632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    }
10930632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
10948ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our position.
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportLocation(int flags, double latitude, double longitude, double altitude,
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float speed, float bearing, float accuracy, long timestamp) {
110029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                " timestamp: " + timestamp);
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mLocation) {
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = flags;
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLatitude(latitude);
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLongitude(longitude);
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setTime(timestamp);
11092eeeec248a38ff33999c83f4b8d5bab7d50e79d2Nick Pelly                // It would be nice to push the elapsed real-time timestamp
11102eeeec248a38ff33999c83f4b8d5bab7d50e79d2Nick Pelly                // further down the stack, but this is still useful
11114118012da9a22694b3353040a485f8cdc27e2f17Philip Milne                mLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAltitude(altitude);
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAltitude();
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setSpeed(speed);
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeSpeed();
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setBearing(bearing);
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeBearing();
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAccuracy(accuracy);
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAccuracy();
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1133ced2b2c09a209e017f02cf28ddd9d35b2d8b8adaSean Barbeau            mLocation.setExtras(mLocationExtras);
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
113515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            try {
11366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                mILocationManager.reportLocation(mLocation, false);
113715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            } catch (RemoteException e) {
113815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Log.e(TAG, "RemoteException calling reportLocation");
113915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1142fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        mLastFixTime = System.currentTimeMillis();
1143fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        // report time to first fix
11446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (mTimeToFirstFix == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
11456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mTimeToFirstFix = (int)(mLastFixTime - mFixRequestTime);
11466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (DEBUG) Log.d(TAG, "TTFF: " + mTimeToFirstFix);
1147fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson
1148fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            // notify status listeners
11496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            synchronized (mListeners) {
1150fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                int size = mListeners.size();
1151fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                for (int i = 0; i < size; i++) {
1152fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    Listener listener = mListeners.get(i);
1153fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    try {
11546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                        listener.mListener.onFirstFix(mTimeToFirstFix);
1155fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    } catch (RemoteException e) {
1156fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        Log.w(TAG, "RemoteException in stopNavigating");
1157fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        mListeners.remove(listener);
1158fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        // adjust for size of list changing
1159fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        size--;
1160fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    }
1161fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                }
1162fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            }
1163fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        }
1164fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson
11651d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt        if (mSingleShot) {
11661d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt            stopNavigating();
11671d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt        }
11681d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt
116915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mStarted && mStatus != LocationProvider.AVAILABLE) {
1170d53ba017ee2381383b4bb4d92e6e0e661431660fMike Lockwood            // we want to time out if we do not receive a fix
1171b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood            // within the time out and we are requesting infrequent fixes
117204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {
1173b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood                mAlarmManager.cancel(mTimeoutIntent);
1174b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood            }
1175b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is receiving fixes.
117700b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
117800b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
11795ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
118015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.AVAILABLE, mSvCount);
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
118229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
1183b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly       if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted &&
1184b041f23026536dd287c1a9a962642c84ebd10004Nick Pelly               mFixInterval > GPS_POLLING_THRESHOLD_INTERVAL) {
1185d53ba017ee2381383b4bb4d92e6e0e661431660fMike Lockwood            if (DEBUG) Log.d(TAG, "got fix, hibernating");
11860632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            hibernate();
118729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        }
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   }
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our status
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportStatus(int status) {
1194b8d9033d9928209e68518c4b12fea74187ddb382Mike Lockwood        if (DEBUG) Log.v(TAG, "reportStatus status: " + status);
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        synchronized (mListeners) {
11972e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            boolean wasNavigating = mNavigating;
1198dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood
1199cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            switch (status) {
1200cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_SESSION_BEGIN:
1201cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mNavigating = true;
1202271f9f172b241607b1ed39a7709c3ed47ee5dee7Mike Lockwood                    mEngineOn = true;
1203cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1204cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_SESSION_END:
1205cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mNavigating = false;
1206cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1207cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_ENGINE_ON:
1208cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mEngineOn = true;
1209cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1210cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_ENGINE_OFF:
1211cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mEngineOn = false;
1212271f9f172b241607b1ed39a7709c3ed47ee5dee7Mike Lockwood                    mNavigating = false;
1213cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1214cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            }
1215cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood
1216dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood            if (wasNavigating != mNavigating) {
1217dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                int size = mListeners.size();
1218dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                for (int i = 0; i < size; i++) {
1219dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    Listener listener = mListeners.get(i);
1220dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    try {
1221dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        if (mNavigating) {
1222dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            listener.mListener.onGpsStarted();
1223dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        } else {
1224dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            listener.mListener.onGpsStopped();
1225dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        }
1226dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    } catch (RemoteException e) {
1227dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        Log.w(TAG, "RemoteException in reportStatus");
1228dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        mListeners.remove(listener);
1229dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        // adjust for size of list changing
1230dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        size--;
1231dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    }
1232dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                }
1233dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood
1234dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                // send an intent to notify that the GPS has been enabled or disabled.
123500b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood                Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
123600b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood                intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
12375ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn                mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
12382f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update SV info
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportSvStatus() {
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
12486fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
12496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        synchronized (mListeners) {
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int size = mListeners.size();
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < size; i++) {
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Listener listener = mListeners.get(i);
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
12546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs,
12556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                            mSvElevations, mSvAzimuths, mSvMasks[EPHEMERIS_MASK],
12566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                            mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK]);
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.w(TAG, "RemoteException in reportSvInfo");
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mListeners.remove(listener);
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // adjust for size of list changing
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    size--;
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
126629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) {
126729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            Log.v(TAG, "SV count: " + svCount +
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) +
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK]));
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < svCount; i++) {
127129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                Log.v(TAG, "sv: " + mSvs[i] +
12726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                        " snr: " + mSnrs[i]/10 +
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " elev: " + mSvElevations[i] +
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " azimuth: " + mSvAzimuths[i] +
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " E") +
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " A") +
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U"));
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12810881f4f9339febee85c9ab4cba69970ac5cbde55Kevin.KY Tsai        // return number of sets used in fix instead of total
12820881f4f9339febee85c9ab4cba69970ac5cbde55Kevin.KY Tsai        updateStatus(mStatus, Integer.bitCount(mSvMasks[USED_FOR_FIX_MASK]));
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
128415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
128504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is no longer receiving fixes.
128700b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
128800b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
12895ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
129015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
129358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
129458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    /**
1295e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood     * called from native code to update AGPS status
129658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood     */
12978efd74dbedb65f69734318d9d6be70767f30b57aStephen Li    private void reportAGpsStatus(int type, int status, int ipaddr) {
129858bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        switch (status) {
1299e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_REQUEST_AGPS_DATA_CONN:
1300b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
13012acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                // Set mAGpsDataConnectionState before calling startUsingNetworkFeature
13022acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                //  to avoid a race condition with handleUpdateNetworkState()
13032acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
13042acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                int result = mConnMgr.startUsingNetworkFeature(
130558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                        ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
13068efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                mAGpsDataConnectionIpAddr = ipaddr;
1307a639b311e93ad14d9ee5c2b2c215ed2d86c32d2aWink Saville                if (result == PhoneConstants.APN_ALREADY_ACTIVE) {
1308a639b311e93ad14d9ee5c2b2c215ed2d86c32d2aWink Saville                    if (DEBUG) Log.d(TAG, "PhoneConstants.APN_ALREADY_ACTIVE");
1309b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    if (mAGpsApn != null) {
13108efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                        Log.d(TAG, "mAGpsDataConnectionIpAddr " + mAGpsDataConnectionIpAddr);
13118efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                        if (mAGpsDataConnectionIpAddr != 0xffffffff) {
13128efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                            boolean route_result;
13138efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                            if (DEBUG) Log.d(TAG, "call requestRouteToHost");
13148efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                            route_result = mConnMgr.requestRouteToHost(
13158efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                                ConnectivityManager.TYPE_MOBILE_SUPL,
13168efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                                mAGpsDataConnectionIpAddr);
13178efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                            if (route_result == false) Log.d(TAG, "call requestRouteToHost failed");
13188efd74dbedb65f69734318d9d6be70767f30b57aStephen Li                        }
1319b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        native_agps_data_conn_open(mAGpsApn);
1320b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
1321b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    } else {
1322a639b311e93ad14d9ee5c2b2c215ed2d86c32d2aWink Saville                        Log.e(TAG, "mAGpsApn not set when receiving PhoneConstants.APN_ALREADY_ACTIVE");
13232acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
1324b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        native_agps_data_conn_failed();
1325b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    }
1326a639b311e93ad14d9ee5c2b2c215ed2d86c32d2aWink Saville                } else if (result == PhoneConstants.APN_REQUEST_STARTED) {
1327a639b311e93ad14d9ee5c2b2c215ed2d86c32d2aWink Saville                    if (DEBUG) Log.d(TAG, "PhoneConstants.APN_REQUEST_STARTED");
13282acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                    // Nothing to do here
132958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else {
13301d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                    if (DEBUG) Log.d(TAG, "startUsingNetworkFeature failed, value is " +
13311d72d8c33d1ecba5b06a87aa06211477345fd4c5Stan Chesnutt                                     result);
13322acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
1333e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_failed();
133458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
133558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1336e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_RELEASE_AGPS_DATA_CONN:
1337b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
1338e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
133958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                    mConnMgr.stopUsingNetworkFeature(
134058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                            ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
1341e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_closed();
1342e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
134358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
134458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1345e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONNECTED:
1346b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
134758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1348e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_DONE:
1349b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
135058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1351e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_FAILED:
1352b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
135358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
135458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        }
135558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    }
135658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1357b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    /**
1358b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood     * called from native code to report NMEA data received
1359b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood     */
1360f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood    private void reportNmea(long timestamp) {
13616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        synchronized (mListeners) {
1362b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            int size = mListeners.size();
1363b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            if (size > 0) {
1364b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                // don't bother creating the String if we have no listeners
1365f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood                int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
1366b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                String nmea = new String(mNmeaBuffer, 0, length);
1367b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood
1368b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                for (int i = 0; i < size; i++) {
1369b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    Listener listener = mListeners.get(i);
1370b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    try {
1371b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        listener.mListener.onNmeaReceived(timestamp, nmea);
1372b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    } catch (RemoteException e) {
1373b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        Log.w(TAG, "RemoteException in reportNmea");
1374b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        mListeners.remove(listener);
1375b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        // adjust for size of list changing
1376b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        size--;
1377b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    }
1378b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                }
1379b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            }
1380b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood        }
1381b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    }
1382b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood
138362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    /**
138404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood     * called from native code to inform us what the GPS engine capabilities are
138504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood     */
138604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private void setEngineCapabilities(int capabilities) {
138704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood        mEngineCapabilities = capabilities;
13889b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood
13899b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood        if (!hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME) && !mPeriodicTimeInjection) {
13909b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            mPeriodicTimeInjection = true;
13919b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            requestUtcTime();
13929b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood        }
139304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    }
139404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
139504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    /**
139662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood     * called from native code to request XTRA data
139762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood     */
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void xtraDownloadRequest() {
1399f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
140098e48691f738680fe59e7383a41458e7337daccdMike Lockwood        sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14038ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    /**
14048ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     * Called from native to report GPS Geofence transition
14058ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     * All geofence callbacks are called on the same thread
14068ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     */
14078ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private void reportGeofenceTransition(int geofenceId, int flags, double latitude,
14088ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            double longitude, double altitude, float speed, float bearing, float accuracy,
14098ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            long timestamp, int transition, long transitionTimestamp) {
14108ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (mGeofenceHardwareImpl == null) {
14118ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
14128ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
14138ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        mGeofenceHardwareImpl.reportGpsGeofenceTransition(geofenceId, flags, latitude, longitude,
14148ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh           altitude, speed, bearing, accuracy, timestamp, transition, transitionTimestamp);
14158ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
14168ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
14178ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    /**
14188ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     * called from native code to report GPS status change.
14198ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     */
14208ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private void reportGeofenceStatus(int status, int flags, double latitude,
14218ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            double longitude, double altitude, float speed, float bearing, float accuracy,
14228ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            long timestamp) {
14238ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (mGeofenceHardwareImpl == null) {
14248ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
14258ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
14268ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        mGeofenceHardwareImpl.reportGpsGeofenceStatus(status, flags, latitude, longitude, altitude,
14278ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            speed, bearing, accuracy, timestamp);
14288ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
14298ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
14308ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    /**
14318ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     * called from native code - Geofence Add callback
14328ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     */
14338ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private void reportGeofenceAddStatus(int geofenceId, int status) {
14348ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (mGeofenceHardwareImpl == null) {
14358ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
14368ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
14378ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        mGeofenceHardwareImpl.reportGpsGeofenceAddStatus(geofenceId, status);
14388ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
14398ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
14408ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    /**
14418ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     * called from native code - Geofence Remove callback
14428ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     */
14438ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private void reportGeofenceRemoveStatus(int geofenceId, int status) {
14448ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (mGeofenceHardwareImpl == null) {
14458ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
14468ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
14478ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        mGeofenceHardwareImpl.reportGpsGeofenceRemoveStatus(geofenceId, status);
14488ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
14498ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
14508ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    /**
14518ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     * called from native code - Geofence Pause callback
14528ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     */
14538ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private void reportGeofencePauseStatus(int geofenceId, int status) {
14548ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (mGeofenceHardwareImpl == null) {
14558ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
14568ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
14578ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        mGeofenceHardwareImpl.reportGpsGeofencePauseStatus(geofenceId, status);
14588ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
14598ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
14608ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    /**
14618ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     * called from native code - Geofence Resume callback
14628ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh     */
14638ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private void reportGeofenceResumeStatus(int geofenceId, int status) {
14648ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        if (mGeofenceHardwareImpl == null) {
14658ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
14668ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        }
14678ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        mGeofenceHardwareImpl.reportGpsGeofenceResumeStatus(geofenceId, status);
14688ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    }
14698ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
147022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    //=============================================================
147122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // NI Client support
14721e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    //=============================================================
147322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
14741e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        // Sends a response for an NI reqeust to HAL.
14756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        @Override
14761e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        public boolean sendNiResponse(int notificationId, int userResponse)
14771e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        {
14781e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            // TODO Add Permission check
14791e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14801e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
14811e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                    ", response: " + userResponse);
14821e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            native_send_ni_response(notificationId, userResponse);
14831e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            return true;
14841e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
148522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    };
14866fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
148722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    public INetInitiatedListener getNetInitiatedListener() {
148822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        return mNetInitiatedListener;
148922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    }
149022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
149122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // Called by JNI function to report an NI request.
14921e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    public void reportNiNotification(
14931e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int notificationId,
14941e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int niType,
14951e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int notifyFlags,
14961e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int timeout,
14971e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int defaultResponse,
14981e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String requestorId,
14991e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String text,
15001e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int requestorIdEncoding,
15011e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int textEncoding,
15021e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String extras  // Encoded extra data
150322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        )
15041e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    {
15051e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Log.i(TAG, "reportNiNotification: entered");
15061e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Log.i(TAG, "notificationId: " + notificationId +
15071e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", niType: " + niType +
15081e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", notifyFlags: " + notifyFlags +
15091e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", timeout: " + timeout +
15101e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", defaultResponse: " + defaultResponse);
15111e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
15121e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Log.i(TAG, "requestorId: " + requestorId +
15131e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", text: " + text +
15141e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", requestorIdEncoding: " + requestorIdEncoding +
15151e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", textEncoding: " + textEncoding);
15161e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
15171e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        GpsNiNotification notification = new GpsNiNotification();
15181e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
15191e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.notificationId = notificationId;
15201e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.niType = niType;
15211e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
15221e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
15231e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
15241e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.timeout = timeout;
15251e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.defaultResponse = defaultResponse;
15261e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.requestorId = requestorId;
15271e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.text = text;
15281e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.requestorIdEncoding = requestorIdEncoding;
15291e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.textEncoding = textEncoding;
15301e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
15311e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        // Process extras, assuming the format is
15321e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        // one of more lines of "key = value"
15331e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Bundle bundle = new Bundle();
15341e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
15351e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        if (extras == null) extras = "";
15361e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Properties extraProp = new Properties();
15371e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
15381e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        try {
1539104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey            extraProp.load(new StringReader(extras));
15401e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
15411e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        catch (IOException e)
15421e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        {
15431e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
15441e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
15451e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
15461e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        for (Entry<Object, Object> ent : extraProp.entrySet())
15471e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        {
15481e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            bundle.putString((String) ent.getKey(), (String) ent.getValue());
15491e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
15501e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
15511e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.extras = bundle;
15521e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
15531e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        mNIHandler.handleNiNotification(notification);
15541e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
15551e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
15561e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    /**
15571e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * Called from native code to request set id info.
15581e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * We should be careful about receiving null string from the TelephonyManager,
15591e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * because sending null String to JNI function would cause a crash.
15601e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     */
15611e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
15621e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void requestSetID(int flags) {
15631e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        TelephonyManager phone = (TelephonyManager)
15641e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                mContext.getSystemService(Context.TELEPHONY_SERVICE);
15651e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        int    type = AGPS_SETID_TYPE_NONE;
15661e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        String data = "";
15671e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
15681e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
15691e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String data_temp = phone.getSubscriberId();
15701e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            if (data_temp == null) {
15711e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework does not have the SIM card ready.
15721e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else {
15731e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework has the SIM card.
15741e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                data = data_temp;
15751e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                type = AGPS_SETID_TYPE_IMSI;
15761e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            }
15771e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
15781e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
15791e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String data_temp = phone.getLine1Number();
15801e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            if (data_temp == null) {
15811e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework does not have the SIM card ready.
15821e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else {
15831e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework has the SIM card.
15841e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                data = data_temp;
15851e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                type = AGPS_SETID_TYPE_MSISDN;
15861e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            }
15871e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
15881e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        native_agps_set_id(type, data);
15891e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
15901e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
15911e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    /**
15929b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood     * Called from native code to request utc time info
15939b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood     */
15949b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood
15959b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    private void requestUtcTime() {
15969b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood        sendMessage(INJECT_NTP_TIME, 0, null);
15979b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    }
15989b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood
15999b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    /**
16001e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * Called from native code to request reference location info
16011e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     */
16021e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
16031e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void requestRefLocation(int flags) {
16041e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        TelephonyManager phone = (TelephonyManager)
16051e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                mContext.getSystemService(Context.TELEPHONY_SERVICE);
1606d50d0c31d4c4472c91bad64d23d2adcaeec010c6Victoria Lease        final int phoneType = phone.getPhoneType();
1607d50d0c31d4c4472c91bad64d23d2adcaeec010c6Victoria Lease        if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
16081e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation();
1609d50d0c31d4c4472c91bad64d23d2adcaeec010c6Victoria Lease            if ((gsm_cell != null) && (phone.getNetworkOperator() != null)
1610d50d0c31d4c4472c91bad64d23d2adcaeec010c6Victoria Lease                    && (phone.getNetworkOperator().length() > 3)) {
16111e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                int type;
16121e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0,3));
16131e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3));
1614edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                int networkType = phone.getNetworkType();
1615edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                if (networkType == TelephonyManager.NETWORK_TYPE_UMTS
1616edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                    || networkType == TelephonyManager.NETWORK_TYPE_HSDPA
1617edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                    || networkType == TelephonyManager.NETWORK_TYPE_HSUPA
161858d46126e4d11e0cc5f6a1192829511bd5850ce2Arun Ravindran                    || networkType == TelephonyManager.NETWORK_TYPE_HSPA
161958d46126e4d11e0cc5f6a1192829511bd5850ce2Arun Ravindran                    || networkType == TelephonyManager.NETWORK_TYPE_HSPAP) {
16201e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                    type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
1621edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                } else {
16221e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                    type = AGPS_REF_LOCATION_TYPE_GSM_CELLID;
1623edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                }
16241e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                native_agps_set_ref_location_cellid(type, mcc, mnc,
16251e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                        gsm_cell.getLac(), gsm_cell.getCid());
1626edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood            } else {
16271e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                Log.e(TAG,"Error getting cell location info.");
1628edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood            }
1629d50d0c31d4c4472c91bad64d23d2adcaeec010c6Victoria Lease        } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
1630d50d0c31d4c4472c91bad64d23d2adcaeec010c6Victoria Lease            Log.e(TAG, "CDMA not supported.");
1631edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood        }
16321e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
163322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
163498e48691f738680fe59e7383a41458e7337daccdMike Lockwood    private void sendMessage(int message, int arg, Object obj) {
16356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // hold a wake lock until this message is delivered
1636028872fe07f9b3468aa1506c658d6aae25f53015Jeff Brown        // note that this assumes the message will not be removed from the queue before
1637028872fe07f9b3468aa1506c658d6aae25f53015Jeff Brown        // it is handled (otherwise the wake lock would be leaked).
16386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mWakeLock.acquire();
16396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mHandler.obtainMessage(message, arg, 1, obj).sendToTarget();
164098e48691f738680fe59e7383a41458e7337daccdMike Lockwood    }
164198e48691f738680fe59e7383a41458e7337daccdMike Lockwood
164262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private final class ProviderHandler extends Handler {
16435cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease        public ProviderHandler(Looper looper) {
16445cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease            super(looper, null, true /*async*/);
1645028872fe07f9b3468aa1506c658d6aae25f53015Jeff Brown        }
1646028872fe07f9b3468aa1506c658d6aae25f53015Jeff Brown
164762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        @Override
16484a7b65e0d544ef1feff8e1e5789f469f89ebb85cMike Lockwood        public void handleMessage(Message msg) {
164998e48691f738680fe59e7383a41458e7337daccdMike Lockwood            int message = msg.what;
165098e48691f738680fe59e7383a41458e7337daccdMike Lockwood            switch (message) {
165162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case ENABLE:
165262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    if (msg.arg1 == 1) {
165362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                        handleEnable();
165462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    } else {
165562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                        handleDisable();
16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
165762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
16586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                case SET_REQUEST:
16596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    GpsRequest gpsRequest = (GpsRequest) msg.obj;
16606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    handleSetRequest(gpsRequest.request, gpsRequest.source);
166103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    break;
166262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case UPDATE_NETWORK_STATE:
166362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleUpdateNetworkState(msg.arg1, (NetworkInfo)msg.obj);
166462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
166562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case INJECT_NTP_TIME:
166662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleInjectNtpTime();
166762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
166862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case DOWNLOAD_XTRA_DATA:
16691a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood                    if (mSupportsXtra) {
167062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                        handleDownloadXtraData();
16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
167262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
167340e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                case INJECT_NTP_TIME_FINISHED:
167440e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    mInjectNtpTimePending = STATE_IDLE;
167540e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    break;
167640e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                case DOWNLOAD_XTRA_DATA_FINISHED:
167740e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    mDownloadXtraDataPending = STATE_IDLE;
167840e1bafc37e2a83453535132c62aeb7ef706de25Kevin Tang                    break;
167962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case UPDATE_LOCATION:
168062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleUpdateLocation((Location)msg.obj);
168162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16836fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (msg.arg2 == 1) {
16846fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // wakelock was taken for this message, release it
16856fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                mWakeLock.release();
168698e48691f738680fe59e7383a41458e7337daccdMike Lockwood            }
16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
168862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    };
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final class NetworkLocationListener implements LocationListener {
16916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        @Override
16926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        public void onLocationChanged(Location location) {
16936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // this callback happens on mHandler looper
16946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
16956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                handleUpdateLocation(location);
16966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
16976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
16986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        @Override
16996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        public void onStatusChanged(String provider, int status, Bundle extras) { }
17006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        @Override
17016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        public void onProviderEnabled(String provider) { }
17026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        @Override
17036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        public void onProviderDisabled(String provider) { }
17046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
17056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1706a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang    private String getSelectedApn() {
1707a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang        Uri uri = Uri.parse("content://telephony/carriers/preferapn");
1708a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang        String apn = null;
1709a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang
1710a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang        Cursor cursor = mContext.getContentResolver().query(uri, new String[] {"apn"},
1711a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                null, null, Carriers.DEFAULT_SORT_ORDER);
1712a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang
1713a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang        if (null != cursor) {
1714a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            try {
1715a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                if (cursor.moveToFirst()) {
1716a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                    apn = cursor.getString(0);
1717a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                }
1718a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            } finally {
1719a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang                cursor.close();
1720a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            }
1721a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang        }
1722a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang        return apn;
1723a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang    }
1724a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang
17256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
17266fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
17276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        StringBuilder s = new StringBuilder();
17286fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        s.append("  mFixInterval=").append(mFixInterval).append("\n");
17296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        s.append("  mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities)).append(" (");
17306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHED ");
17316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
17326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA ");
17336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT ");
17346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME ");
17356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        s.append(")\n");
17366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
17376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        s.append(native_get_internal_state());
17386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        pw.append(s);
17396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
17406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
17419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for GPS SV statistics
17429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int MAX_SVS = 32;
17439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int EPHEMERIS_MASK = 0;
17449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int ALMANAC_MASK = 1;
17459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int USED_FOR_FIX_MASK = 2;
17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // preallocated arrays, to avoid memory allocation in reportStatus()
17489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvs[] = new int[MAX_SVS];
17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSnrs[] = new float[MAX_SVS];
17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvElevations[] = new float[MAX_SVS];
17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvAzimuths[] = new float[MAX_SVS];
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvMasks[] = new int[3];
17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvCount;
1754b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    // preallocated to avoid memory allocation in reportNmea()
1755b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    private byte[] mNmeaBuffer = new byte[120];
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static { class_init_native(); }
17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native void class_init_native();
17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native boolean native_is_supported();
17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_init();
17629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_cleanup();
176304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private native boolean native_set_position_mode(int mode, int recurrence, int min_interval,
176404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            int preferred_accuracy, int preferred_time);
176504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private native boolean native_start();
17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_stop();
17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_delete_aiding_data(int flags);
17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // returns number of SVs
17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // mask[0] is ephemeris mask and mask[1] is almanac mask
17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native int native_read_sv_status(int[] svs, float[] snrs,
17719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] elevations, float[] azimuths, int[] masks);
1772f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood    private native int native_read_nmea(byte[] buffer, int bufferSize);
1773d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood    private native void native_inject_location(double latitude, double longitude, float accuracy);
1774d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood
17753c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    // XTRA Support
17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_time(long time, long timeReference, int uncertainty);
17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_supports_xtra();
17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_xtra_data(byte[] data, int length);
1779105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
17803c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    // DEBUG Support
17813c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    private native String native_get_internal_state();
17823c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger
17833c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    // AGPS Support
1784e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_open(String apn);
1785e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_closed();
1786e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_failed();
17871e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private native void native_agps_ni_message(byte [] msg, int length);
1788a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood    private native void native_set_agps_server(int type, String hostname, int port);
178922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
179022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // Network-initiated (NI) Support
179122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private native void native_send_ni_response(int notificationId, int userResponse);
17921e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
17931e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // AGPS ril suport
17941e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
17951e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int lac, int cid);
17961e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private native void native_agps_set_id(int type, String setid);
179750130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood
179850130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood    private native void native_update_network_state(boolean connected, int type,
1799a5fe6b2efee02ab11c35e80ec50fec62be227273Kevin Tang            boolean roaming, boolean available, String extraInfo, String defaultAPN);
18008ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
18018ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    // Hardware Geofence support.
18028ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static native boolean native_is_geofence_supported();
18038ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static native boolean native_add_geofence(int geofenceId, double latitude,
18048ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            double longitude, double radius, int lastTransition,int monitorTransitions,
18058ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh            int notificationResponsivenes, int unknownTimer);
18068ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static native boolean native_remove_geofence(int geofenceId);
18078ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static native boolean native_resume_geofence(int geofenceId, int transitions);
18088ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh    private static native boolean native_pause_geofence(int geofenceId);
18099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1810