GpsLocationProvider.java revision 104344e507610be42fb70c7deda3c422c543bfcb
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1700b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwoodpackage com.android.server.location;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1929c84340a14e70419449628ab193d11b7a609e9aMike Lockwoodimport android.app.AlarmManager;
2029c84340a14e70419449628ab193d11b7a609e9aMike Lockwoodimport android.app.PendingIntent;
21105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.content.BroadcastReceiver;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
24105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.content.IntentFilter;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Criteria;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.IGpsStatusListener;
2715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwoodimport android.location.IGpsStatusProvider;
284e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwoodimport android.location.ILocationManager;
2922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport android.location.INetInitiatedListener;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Location;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationManager;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationProvider;
3358bda987665af759c379cd494ff4873ac61acf29Mike Lockwoodimport android.net.ConnectivityManager;
3403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwoodimport android.net.NetworkInfo;
3563aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwoodimport android.os.Binder;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
3762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwoodimport android.os.Handler;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
3962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwoodimport android.os.Looper;
4062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwoodimport android.os.Message;
410528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwoodimport android.os.PowerManager;
4262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwoodimport android.os.Process;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
442f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport android.os.ServiceManager;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
467e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackbornimport android.os.WorkSource;
47bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwoodimport android.provider.Settings;
481e84da822e7aa4d494b31c8759917d2751611f84Miguel Torrojaimport android.provider.Telephony.Sms.Intents;
49b49a73dfc4c9817bba1f227e9330555acdf9b56fJake Hambyimport android.telephony.SmsMessage;
501e84da822e7aa4d494b31c8759917d2751611f84Miguel Torrojaimport android.telephony.TelephonyManager;
511e84da822e7aa4d494b31c8759917d2751611f84Miguel Torrojaimport android.telephony.gsm.GsmCellLocation;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
53104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkeyimport android.util.NtpTrustedTime;
542f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport android.util.SparseIntArray;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
562f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport com.android.internal.app.IBatteryStats;
5722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport com.android.internal.location.GpsNetInitiatedHandler;
5822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
59b49a73dfc4c9817bba1f227e9330555acdf9b56fJake Hambyimport com.android.internal.telephony.Phone;
60105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileInputStream;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
64104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkeyimport java.io.StringReader;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
66f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwoodimport java.util.Date;
6722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport java.util.Map.Entry;
68b49a73dfc4c9817bba1f227e9330555acdf9b56fJake Hambyimport java.util.Properties;
6989096317104722219f73a5c3cc424e6e98c90a61Mike Lockwoodimport java.util.concurrent.CountDownLatch;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A GPS implementation of LocationProvider used by LocationManager.
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
7689096317104722219f73a5c3cc424e6e98c90a61Mike Lockwoodpublic class GpsLocationProvider implements LocationProviderInterface {
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "GpsLocationProvider";
7929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
804a7b65e0d544ef1feff8e1e5789f469f89ebb85cMike Lockwood    private static final boolean DEBUG = false;
8129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private static final boolean VERBOSE = false;
8262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
83105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    // these need to match GpsPositionMode enum in gps.h
84105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_STANDALONE = 0;
85105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_MS_BASED = 1;
86105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
87105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
8804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // these need to match GpsPositionRecurrence enum in gps.h
8904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_POSITION_RECURRENCE_PERIODIC = 0;
9004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_POSITION_RECURRENCE_SINGLE = 1;
9104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these need to match GpsStatusValue defines in gps.h
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_NONE = 0;
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_SESSION_BEGIN = 1;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_SESSION_END = 2;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_ENGINE_ON = 3;
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_ENGINE_OFF = 4;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
99e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // these need to match GpsApgsStatusValue defines in gps.h
100e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    /** AGPS status event values. */
101e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
102e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
103e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONNECTED = 3;
104e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONN_DONE = 4;
105e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
10658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these need to match GpsLocationFlags enum in gps.h
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_INVALID = 0;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_LAT_LONG = 1;
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_ALTITUDE = 2;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_SPEED = 4;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_BEARING = 8;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_ACCURACY = 16;
114e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
115e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood// IMPORTANT - the GPS_DELETE_* symbols here must match constants in gps.h
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_EPHEMERIS = 0x0001;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_ALMANAC = 0x0002;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_POSITION = 0x0004;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_TIME = 0x0008;
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_IONO = 0x0010;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_UTC = 0x0020;
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_HEALTH = 0x0040;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SVDIR = 0x0080;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SVSTEER = 0x0100;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SADATA = 0x0200;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_RTI = 0x0400;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_ALL = 0xFFFF;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // The GPS_CAPABILITY_* flags must match the values in gps.h
13104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_SCHEDULING = 0x0000001;
13204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_MSB = 0x0000002;
13304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_MSA = 0x0000004;
13404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
1359b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010;
13604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
137e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // these need to match AGpsType enum in gps.h
138e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_TYPE_SUPL = 1;
139e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_TYPE_C2K = 2;
140e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
141e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // for mAGpsDataConnectionState
142e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
143e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_OPENING = 1;
144e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_OPEN = 2;
14558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
14662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    // Handler messages
14762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int CHECK_LOCATION = 1;
14862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int ENABLE = 2;
14962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int ENABLE_TRACKING = 3;
15062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int UPDATE_NETWORK_STATE = 4;
15162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int INJECT_NTP_TIME = 5;
15262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int DOWNLOAD_XTRA_DATA = 6;
15362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int UPDATE_LOCATION = 7;
15462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int ADD_LISTENER = 8;
15562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int REMOVE_LISTENER = 9;
15603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private static final int REQUEST_SINGLE_SHOT = 10;
15762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
1581e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // Request setid
1591e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
1601e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2;
1611e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
1621e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // Request ref location
1631e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_RIL_REQUEST_REFLOC_CELLID = 1;
1641e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_RIL_REQUEST_REFLOC_MAC = 2;
1651e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
1661e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // ref. location info
1671e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
1681e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
1691e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_REG_LOCATION_TYPE_MAC        = 3;
1701e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
1711e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // set id info
1721e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_SETID_TYPE_NONE = 0;
1731e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_SETID_TYPE_IMSI = 1;
1741e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private static final int AGPS_SETID_TYPE_MSISDN = 2;
1751e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String PROPERTIES_FILE = "/etc/gps.conf";
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mLocationFlags = LOCATION_INVALID;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current status
18115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time for last status update
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mStatusUpdateTime = SystemClock.elapsedRealtime();
185d53ba017ee2381383b4bb4d92e6e0e661431660fMike Lockwood
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // turn off GPS fix icon if we haven't received a fix in 10 seconds
18704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final long RECENT_FIX_TIMEOUT = 10 * 1000;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1890632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    // stop trying if we do not receive a fix within 60 seconds
19004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int NO_FIX_TIMEOUT = 60 * 1000;
1910632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we are enabled
19389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private volatile boolean mEnabled;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we have network connectivity
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNetworkAvailable;
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    // flags to trigger NTP or XTRA data download when network becomes available
19962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    // initialized to true so we do NTP and XTRA when the network comes up after booting
20062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private boolean mInjectNtpTimePending = true;
2015982bf66d4fdea38105d91ff0f9d38660ac87581Mike Lockwood    private boolean mDownloadXtraDataPending = true;
20262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
2039b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    // set to true if the GPS engine does not do on-demand NTP time requests
2049b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    private boolean mPeriodicTimeInjection;
2059b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if GPS is navigating
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNavigating;
208cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood
209cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood    // true if GPS engine is on
210cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood    private boolean mEngineOn;
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // requested frequency of fixes, in milliseconds
21304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private int mFixInterval = 1000;
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we started navigation
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mStarted;
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    // true if single shot request is in progress
21903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private boolean mSingleShot;
22003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
22104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // capabilities of the GPS engine
22204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private int mEngineCapabilities;
22304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
2241a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood    // true if XTRA is supported
2251a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood    private boolean mSupportsXtra;
2261a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for calculating time to first fix
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mFixRequestTime = 0;
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time to first fix for most recent session
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mTTFF = 0;
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time we received our last fix
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mLastFixTime;
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private int mPositionMode;
23504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // properties loaded from PROPERTIES_FILE
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Properties mProperties;
238734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private String mSuplServerHost;
239734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private int mSuplServerPort;
240734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private String mC2KServerHost;
241734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private int mC2KServerPort;
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final Context mContext;
244104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey    private final NtpTrustedTime mNtpTime;
24515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final ILocationManager mLocationManager;
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Bundle mLocationExtras = new Bundle();
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<Listener> mListeners = new ArrayList<Listener>();
24962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
25089096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    // GpsLocationProvider's handler thread
25189096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private final Thread mThread;
25289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    // Handler for processing events in mThread.
25362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private Handler mHandler;
25489096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    // Used to signal when our main thread has initialized everything
25589096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private final CountDownLatch mInitializedLatch = new CountDownLatch(1);
256105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
257e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private String mAGpsApn;
258e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private int mAGpsDataConnectionState;
2592f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final ConnectivityManager mConnMgr;
26022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private final GpsNetInitiatedHandler mNIHandler;
2612f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
2620528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    // Wakelocks
2630528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final static String WAKELOCK_KEY = "GpsLocationProvider";
2640528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final PowerManager.WakeLock mWakeLock;
26598e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // bitfield of pending messages to our Handler
26698e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // used only for messages that cannot have multiple instances queued
26798e48691f738680fe59e7383a41458e7337daccdMike Lockwood    private int mPendingMessageBits;
26898e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // separate counter for ADD_LISTENER and REMOVE_LISTENER messages,
26998e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // which might have multiple instances queued
27098e48691f738680fe59e7383a41458e7337daccdMike Lockwood    private int mPendingListenerMessages;
2710528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
27229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    // Alarms
27329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
2740632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
27529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final AlarmManager mAlarmManager;
27629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final PendingIntent mWakeupIntent;
2770632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final PendingIntent mTimeoutIntent;
27829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
2792f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final IBatteryStats mBatteryStats;
2802f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final SparseIntArray mClientUids = new SparseIntArray();
281105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // how often to request NTP time, in milliseconds
2834c126068527c9adba45aa227d40e245ee8e7c9a4Mike Lockwood    // current setting 24 hours
2844c126068527c9adba45aa227d40e245ee8e7c9a4Mike Lockwood    private static final long NTP_INTERVAL = 24*60*60*1000;
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // how long to wait if we have a network error in NTP or XTRA downloading
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current setting - 5 minutes
287f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood    private static final long RETRY_INTERVAL = 5*60*1000;
288f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood
28915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
29015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
29115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
29215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
29315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
29415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
29515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            synchronized(mListeners) {
29615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
29715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
29815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size; i++) {
29915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
30015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
30115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        // listener already added
30215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        return;
30315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
30415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
30515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
30615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = new Listener(listener);
30715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                binder.linkToDeath(l, 0);
30815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                mListeners.add(l);
30915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
31015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
31115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
31215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void removeGpsStatusListener(IGpsStatusListener listener) {
31315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
31415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
31515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
31615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
31715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            synchronized(mListeners) {
31815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
31915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = null;
32015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
32115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size && l == null; i++) {
32215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
32315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
32415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        l = test;
32515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
32615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
32715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
32815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                if (l != null) {
32915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    mListeners.remove(l);
33015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    binder.unlinkToDeath(l, 0);
33115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
33215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
33315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
33415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    };
33515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
33615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    public IGpsStatusProvider getGpsStatusProvider() {
33715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        return mGpsStatusProvider;
33815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
33915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
34029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
341105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        @Override public void onReceive(Context context, Intent intent) {
342105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            String action = intent.getAction();
343105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
34429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (action.equals(ALARM_WAKEUP)) {
34529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_WAKEUP");
34603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                startNavigating(false);
3470632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            } else if (action.equals(ALARM_TIMEOUT)) {
3480632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");
3490632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                hibernate();
3501e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {
3511e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                checkSmsSuplInit(intent);
3521e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
3531e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                checkWapSuplInit(intent);
3541e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja             }
355105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
35629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    };
357105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
3581e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void checkSmsSuplInit(Intent intent) {
3591e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        SmsMessage[] messages = Intents.getMessagesFromIntent(intent);
3601e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        for (int i=0; i <messages.length; i++) {
3611e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            byte[] supl_init = messages[i].getUserData();
3621e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            native_agps_ni_message(supl_init,supl_init.length);
3631e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
3641e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
3651e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
3661e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void checkWapSuplInit(Intent intent) {
3671e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        byte[] supl_init = (byte[]) intent.getExtra("data");
3681e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        native_agps_ni_message(supl_init,supl_init.length);
3691e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
3701e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean isSupported() {
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_is_supported();
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3754e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    public GpsLocationProvider(Context context, ILocationManager locationManager) {
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
377104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey        mNtpTime = NtpTrustedTime.getInstance(context);
37815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mLocationManager = locationManager;
37979e642e8ed75033eacc461633a8f4cd5157d25dfMike Lockwood        mNIHandler = new GpsNetInitiatedHandler(context);
38063598a0619776b421f27cd12fb29eb83dc327997Mike Lockwood
38163598a0619776b421f27cd12fb29eb83dc327997Mike Lockwood        mLocation.setExtras(mLocationExtras);
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3830528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // Create a wake lock
3840528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
3850528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
38698e48691f738680fe59e7383a41458e7337daccdMike Lockwood        mWakeLock.setReferenceCounted(false);
3870528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
38829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
38929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
3900632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
39129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
3921e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        IntentFilter intentFilter = new IntentFilter();
3931e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
3941e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter.addDataScheme("sms");
3951e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter.addDataAuthority("localhost","7275");
3961e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        context.registerReceiver(mBroadcastReciever, intentFilter);
3971e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
3981e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter = new IntentFilter();
3991e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
4001e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        try {
4011e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            intentFilter.addDataType("application/vnd.omaloc-supl-init");
4021e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        } catch (IntentFilter.MalformedMimeTypeException e) {
4031e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            Log.w(TAG, "Malformed SUPL init mime type");
4041e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
4051e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        context.registerReceiver(mBroadcastReciever, intentFilter);
4061e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
40758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
40858bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
4092f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        // Battery statistics service to be notified when GPS turns on or off
4102f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
4112f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProperties = new Properties();
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            File file = new File(PROPERTIES_FILE);
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            FileInputStream stream = new FileInputStream(file);
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProperties.load(stream);
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stream.close();
418e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
419734d6031a662a275ec68627bd1258159041d44deMike Lockwood            mSuplServerHost = mProperties.getProperty("SUPL_HOST");
420e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            String portString = mProperties.getProperty("SUPL_PORT");
421734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mSuplServerHost != null && portString != null) {
422105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                try {
423734d6031a662a275ec68627bd1258159041d44deMike Lockwood                    mSuplServerPort = Integer.parseInt(portString);
424105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                } catch (NumberFormatException e) {
425e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
426e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                }
427e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            }
428e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
429734d6031a662a275ec68627bd1258159041d44deMike Lockwood            mC2KServerHost = mProperties.getProperty("C2K_HOST");
430e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            portString = mProperties.getProperty("C2K_PORT");
431734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mC2KServerHost != null && portString != null) {
432e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                try {
433734d6031a662a275ec68627bd1258159041d44deMike Lockwood                    mC2KServerPort = Integer.parseInt(portString);
434e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                } catch (NumberFormatException e) {
435e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse C2K_PORT: " + portString);
436105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                }
437105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
44162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
44289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        // wait until we are fully initialized before returning
44389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        mThread = new GpsLocationProviderThread();
44489096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        mThread.start();
44589096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        while (true) {
44689096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            try {
44789096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood                mInitializedLatch.await();
44889096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood                break;
44989096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            } catch (InterruptedException e) {
45089096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood                Thread.currentThread().interrupt();
45189096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            }
45289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        }
45362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
45462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
45562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void initialize() {
45662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        // register our receiver on our thread rather than the main thread
45762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        IntentFilter intentFilter = new IntentFilter();
45862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        intentFilter.addAction(ALARM_WAKEUP);
45962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        intentFilter.addAction(ALARM_TIMEOUT);
46062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mContext.registerReceiver(mBroadcastReciever, intentFilter);
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
464d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood     * Returns the name of this provider.
465d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood     */
466d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    public String getName() {
467d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        return LocationManager.GPS_PROVIDER;
468d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    }
469d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood
470d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    /**
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to a
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * data network (e.g., the Internet), false otherwise.
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresNetwork() {
475a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood        return true;
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
47803d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood    public void updateNetworkState(int state, NetworkInfo info) {
47998e48691f738680fe59e7383a41458e7337daccdMike Lockwood        sendMessage(UPDATE_NETWORK_STATE, state, info);
48062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
48162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
48262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleUpdateNetworkState(int state, NetworkInfo info) {
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNetworkAvailable = (state == LocationProvider.AVAILABLE);
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
485f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) {
48603d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            Log.d(TAG, "updateNetworkState " + (mNetworkAvailable ? "available" : "unavailable")
48703d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                + " info: " + info);
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
48903d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood
49050130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood        if (info != null) {
49150130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood            native_update_network_state(info.isConnected(), info.getType(),
49250130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood                    info.isRoaming(), info.getExtraInfo());
49350130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood        }
49450130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood
49503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood        if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL
49603d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
49703d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            String apnName = info.getExtraInfo();
49803d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            if (mNetworkAvailable && apnName != null && apnName.length() > 0) {
49903d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsApn = apnName;
50003d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                if (DEBUG) Log.d(TAG, "call native_agps_data_conn_open");
50103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                native_agps_data_conn_open(apnName);
50203d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
50303d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            } else {
50403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                if (DEBUG) Log.d(TAG, "call native_agps_data_conn_failed");
50503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsApn = null;
50603d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
50703d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                native_agps_data_conn_failed();
50803d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            }
50903d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood        }
51003d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood
51162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (mNetworkAvailable) {
51262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (mInjectNtpTimePending) {
51398e48691f738680fe59e7383a41458e7337daccdMike Lockwood                sendMessage(INJECT_NTP_TIME, 0, null);
51462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            }
51562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (mDownloadXtraDataPending) {
51698e48691f738680fe59e7383a41458e7337daccdMike Lockwood                sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
51762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            }
51862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
51962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
52062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
52162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleInjectNtpTime() {
52262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (!mNetworkAvailable) {
52362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            // try again when network is up
52462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mInjectNtpTimePending = true;
52562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            return;
52662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
52762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mInjectNtpTimePending = false;
52862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
52962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        long delay;
53062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
531104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey        // force refresh NTP cache when outdated
532104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey        if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
533104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey            mNtpTime.forceRefresh();
534104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey        }
535104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey
536104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey        // only update when NTP time is fresh
537104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey        if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
538104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey            long time = mNtpTime.getCachedNtpTime();
539104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey            long timeReference = mNtpTime.getCachedNtpTimeReference();
540104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey            long certainty = mNtpTime.getCacheCertainty();
54162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            long now = System.currentTimeMillis();
54262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
54362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            Log.d(TAG, "NTP server returned: "
54462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    + time + " (" + new Date(time)
54562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    + ") reference: " + timeReference
54662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    + " certainty: " + certainty
5471879d284bf3dd704dbc8c95aad262ebbe3c3c0a4Mike Lockwood                    + " system time offset: " + (time - now));
54862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
549104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey            native_inject_time(time, timeReference, (int) certainty);
55062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            delay = NTP_INTERVAL;
55162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        } else {
55262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (DEBUG) Log.d(TAG, "requestTime failed");
55362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            delay = RETRY_INTERVAL;
55462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
55562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
5569b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood        if (mPeriodicTimeInjection) {
5579b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            // send delayed message for next NTP injection
5589b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            // since this is delayed and not urgent we do not hold a wake lock here
5599b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            mHandler.removeMessages(INJECT_NTP_TIME);
5609b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            mHandler.sendMessageDelayed(Message.obtain(mHandler, INJECT_NTP_TIME), delay);
5619b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood        }
56262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
56362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
56462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleDownloadXtraData() {
5655723dfe8c87d0887b8926f43637ed300466890d2Mike Lockwood        if (!mNetworkAvailable) {
56662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            // try again when network is up
56762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mDownloadXtraDataPending = true;
56862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            return;
56962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
57062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mDownloadXtraDataPending = false;
57162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
57262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
57362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
57462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        byte[] data = xtraDownloader.downloadXtraData();
57562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (data != null) {
57662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (DEBUG) {
57762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                Log.d(TAG, "calling native_inject_xtra_data");
57862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            }
57962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            native_inject_xtra_data(data, data.length);
58062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        } else {
58162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            // try again later
58298e48691f738680fe59e7383a41458e7337daccdMike Lockwood            // since this is delayed and not urgent we do not hold a wake lock here
58362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mHandler.removeMessages(DOWNLOAD_XTRA_DATA);
58462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mHandler.sendMessageDelayed(Message.obtain(mHandler, DOWNLOAD_XTRA_DATA), RETRY_INTERVAL);
58562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
589fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     * This is called to inform us when another location provider returns a location.
590fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     * Someday we might use this for network location injection to aid the GPS
591fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     */
592fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    public void updateLocation(Location location) {
59398e48691f738680fe59e7383a41458e7337daccdMike Lockwood        sendMessage(UPDATE_LOCATION, 0, location);
59462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
59562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
59662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleUpdateLocation(Location location) {
597d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        if (location.hasAccuracy()) {
598d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood            native_inject_location(location.getLatitude(), location.getLongitude(),
599d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood                    location.getAccuracy());
600d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        }
601fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    }
602fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood
603fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    /**
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to a
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * satellite-based positioning system (e.g., GPS), false
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise.
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresSatellite() {
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to an appropriate
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * cellular network (e.g., to make use of cell tower IDs), false
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise.
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresCell() {
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the use of this provider may result in a
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * monetary charge to the user, false if use is free.  It is up to
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * each provider to give accurate information.
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasMonetaryCost() {
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide altitude
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports altitude
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsAltitude() {
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide speed
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports speed
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsSpeed() {
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide bearing
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports bearing
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsBearing() {
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the power requirement for this provider.
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the power requirement for this provider, as one of the
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * constants Criteria.POWER_REQUIREMENT_*.
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getPowerRequirement() {
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Criteria.POWER_HIGH;
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
67103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood     * Returns true if this provider meets the given criteria,
67203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood     * false otherwise.
67303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood     */
67403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public boolean meetsCriteria(Criteria criteria) {
67503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        return (criteria.getPowerRequirement() != Criteria.POWER_LOW);
67603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
67703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
67803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    /**
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the horizontal accuracy of this provider
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the accuracy of location from this provider, as one
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of the constants Criteria.ACCURACY_*.
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getAccuracy() {
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Criteria.ACCURACY_FINE;
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Enables this provider.  When enabled, calls to getStatus()
6904e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * must be handled.  Hardware may be started up
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the provider is enabled.
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
69362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    public void enable() {
69462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        synchronized (mHandler) {
69598e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(ENABLE, 1, null);
69662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
69762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
69862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
69962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleEnable() {
70062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (DEBUG) Log.d(TAG, "handleEnable");
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabled) return;
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnabled = native_init();
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabled) {
7051a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood            mSupportsXtra = native_supports_xtra();
706734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mSuplServerHost != null) {
707734d6031a662a275ec68627bd1258159041d44deMike Lockwood                native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
708734d6031a662a275ec68627bd1258159041d44deMike Lockwood            }
709734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mC2KServerHost != null) {
710734d6031a662a275ec68627bd1258159041d44deMike Lockwood                native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
711734d6031a662a275ec68627bd1258159041d44deMike Lockwood            }
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Failed to enable location provider");
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Disables this provider.  When disabled, calls to getStatus()
7194e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * need not be handled.  Hardware may be shut
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * down while the provider is disabled.
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
72262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    public void disable() {
72362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        synchronized (mHandler) {
72498e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(ENABLE, 0, null);
72562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
72662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
72762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
72862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleDisable() {
72989096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        if (DEBUG) Log.d(TAG, "handleDisable");
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mEnabled) return;
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnabled = false;
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        stopNavigating();
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
735cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood        // do this before releasing wakelock
736cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood        native_cleanup();
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
739d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    public boolean isEnabled() {
740d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        return mEnabled;
741d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    }
742d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getStatus(Bundle extras) {
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras != null) {
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            extras.putInt("satellites", mSvCount);
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatus;
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateStatus(int status, int svCount) {
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (status != mStatus || svCount != mSvCount) {
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatus = status;
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSvCount = svCount;
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationExtras.putInt("satellites", svCount);
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatusUpdateTime = SystemClock.elapsedRealtime();
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public long getStatusUpdateTime() {
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatusUpdateTime;
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void enableLocationTracking(boolean enable) {
76403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        // FIXME - should set a flag here to avoid race conditions with single shot request
76562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        synchronized (mHandler) {
76698e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(ENABLE_TRACKING, (enable ? 1 : 0), null);
76762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
76862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
76962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
77062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleEnableLocationTracking(boolean enable) {
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (enable) {
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = 0;
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
77403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            startNavigating(false);
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
77604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
77704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                mAlarmManager.cancel(mWakeupIntent);
77804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                mAlarmManager.cancel(mTimeoutIntent);
77904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            }
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stopNavigating();
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
78403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public boolean requestSingleShotFix() {
78503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        if (mStarted) {
78603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            // cannot do single shot if already navigating
78703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            return false;
78803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
78903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        synchronized (mHandler) {
79003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mHandler.removeMessages(REQUEST_SINGLE_SHOT);
79103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            Message m = Message.obtain(mHandler, REQUEST_SINGLE_SHOT);
79203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mHandler.sendMessage(m);
79303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
79403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        return true;
79503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
79603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
79703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private void handleRequestSingleShot() {
79803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        mTTFF = 0;
79903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        mLastFixTime = 0;
80003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        startNavigating(true);
80103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
80203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
8037e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn    public void setMinTime(long minTime, WorkSource ws) {
804f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) Log.d(TAG, "setMinTime " + minTime);
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (minTime >= 0) {
80704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            mFixInterval = (int)minTime;
80804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
80904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
81004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
81104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                        mFixInterval, 0, 0)) {
81204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                    Log.e(TAG, "set_position_mode failed in setMinTime()");
81304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                }
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8183c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    public String getInternalState() {
8193c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger        return native_get_internal_state();
8203c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    }
8213c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final class Listener implements IBinder.DeathRecipient {
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IGpsStatusListener mListener;
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int mSensors = 0;
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Listener(IGpsStatusListener listener) {
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = listener;
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
832f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato            if (DEBUG) Log.d(TAG, "GPS status listener died");
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(mListeners) {
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mListeners.remove(this);
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
837fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu            if (mListener != null) {
838fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu                mListener.asBinder().unlinkToDeath(this, 0);
839fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu            }
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8432f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    public void addListener(int uid) {
84498e48691f738680fe59e7383a41458e7337daccdMike Lockwood        synchronized (mWakeLock) {
84598e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mPendingListenerMessages++;
8467e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            mWakeLock.acquire();
84798e48691f738680fe59e7383a41458e7337daccdMike Lockwood            Message m = Message.obtain(mHandler, ADD_LISTENER);
84898e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.arg1 = uid;
84998e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.sendMessage(m);
85098e48691f738680fe59e7383a41458e7337daccdMike Lockwood        }
85162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
85262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
85362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleAddListener(int uid) {
8542e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
8552e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mClientUids.indexOfKey(uid) >= 0) {
8562e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                // Shouldn't be here -- already have this uid.
8572e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                Log.w(TAG, "Duplicate add listener for uid " + uid);
8582e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                return;
8592e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            }
8602e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            mClientUids.put(uid, 0);
8612e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mNavigating) {
8622e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
8632e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    mBatteryStats.noteStartGps(uid);
8642e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
8652e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in addListener");
8662e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                }
8672f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
8682f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
8692f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
8702f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8712f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    public void removeListener(int uid) {
87298e48691f738680fe59e7383a41458e7337daccdMike Lockwood        synchronized (mWakeLock) {
87398e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mPendingListenerMessages++;
87498e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mWakeLock.acquire();
87598e48691f738680fe59e7383a41458e7337daccdMike Lockwood            Message m = Message.obtain(mHandler, REMOVE_LISTENER);
87698e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.arg1 = uid;
87798e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.sendMessage(m);
87898e48691f738680fe59e7383a41458e7337daccdMike Lockwood        }
87962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
88062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
88162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleRemoveListener(int uid) {
8822e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
8832e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mClientUids.indexOfKey(uid) < 0) {
8842e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                // Shouldn't be here -- don't have this uid.
8852e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                Log.w(TAG, "Unneeded remove listener for uid " + uid);
8862e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                return;
8872e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            }
8882e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            mClientUids.delete(uid);
8892e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mNavigating) {
8902e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
8912e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    mBatteryStats.noteStopGps(uid);
8922e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
8932e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in removeListener");
8942e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                }
8952f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
8962f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
8972f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
8982f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendExtraCommand(String command, Bundle extras) {
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
90163aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        long identity = Binder.clearCallingIdentity();
90263aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        boolean result = false;
90363aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ("delete_aiding_data".equals(command)) {
90563aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood            result = deleteAidingData(extras);
90663aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        } else if ("force_time_injection".equals(command)) {
90798e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(INJECT_NTP_TIME, 0, null);
90863aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood            result = true;
90963aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        } else if ("force_xtra_injection".equals(command)) {
9101a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood            if (mSupportsXtra) {
91193bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                xtraDownloadRequest();
91263aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood                result = true;
91393bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            }
91463aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        } else {
91563aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood            Log.w(TAG, "sendExtraCommand: unknown command " + command);
91693bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
91863aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        Binder.restoreCallingIdentity(identity);
91963aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        return result;
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean deleteAidingData(Bundle extras) {
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags;
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras == null) {
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = GPS_DELETE_ALL;
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = 0;
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (flags != 0) {
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_delete_aiding_data(flags);
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
95203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private void startNavigating(boolean singleShot) {
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStarted) {
95429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (DEBUG) Log.d(TAG, "startNavigating");
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = true;
95603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mSingleShot = singleShot;
95703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mPositionMode = GPS_POSITION_MODE_STANDALONE;
95803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
95903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood             if (Settings.Secure.getInt(mContext.getContentResolver(),
960660bbfcc54d48d5d32e64da683c76b9c372c19b1Mike Lockwood                    Settings.Secure.ASSISTED_GPS_ENABLED, 1) != 0) {
96103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                if (singleShot && hasCapability(GPS_CAPABILITY_MSA)) {
96203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    mPositionMode = GPS_POSITION_MODE_MS_ASSISTED;
9638dc16c27e23dae5bdf65fd2a2ced97c2f645a633Mike Lockwood                } else if (hasCapability(GPS_CAPABILITY_MSB)) {
96403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    mPositionMode = GPS_POSITION_MODE_MS_BASED;
96503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                }
966bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood            }
967bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood
96804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
96904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
97004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                    interval, 0, 0)) {
97104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                mStarted = false;
97204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                Log.e(TAG, "set_position_mode failed in startNavigating()");
97304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                return;
97404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            }
97504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!native_start()) {
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStarted = false;
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.e(TAG, "native_start failed in startNavigating()");
9780632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                return;
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
98215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
98329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            mFixRequestTime = System.currentTimeMillis();
98404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
98504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
98604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                // and our fix interval is not short
98704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                if (mFixInterval >= NO_FIX_TIMEOUT) {
98804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                    mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
98904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                            SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
99004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                }
9910632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            }
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
99562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void stopNavigating() {
99629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (DEBUG) Log.d(TAG, "stopNavigating");
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mStarted) {
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = false;
99903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mSingleShot = false;
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_stop();
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = 0;
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = LOCATION_INVALID;
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
100615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10100632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private void hibernate() {
10110632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        // stop GPS until our next fix interval arrives
10120632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        stopNavigating();
10130632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mTimeoutIntent);
10140632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mWakeupIntent);
10150632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        long now = SystemClock.elapsedRealtime();
10160632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
101704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                SystemClock.elapsedRealtime() + mFixInterval, mWakeupIntent);
101804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    }
101904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
102004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private boolean hasCapability(int capability) {
102104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood        return ((mEngineCapabilities & capability) != 0);
10220632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    }
10230632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our position.
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportLocation(int flags, double latitude, double longitude, double altitude,
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float speed, float bearing, float accuracy, long timestamp) {
102929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                " timestamp: " + timestamp);
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mLocation) {
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = flags;
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLatitude(latitude);
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLongitude(longitude);
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setTime(timestamp);
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAltitude(altitude);
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAltitude();
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setSpeed(speed);
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeSpeed();
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setBearing(bearing);
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeBearing();
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAccuracy(accuracy);
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAccuracy();
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
106015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            try {
1061a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                mLocationManager.reportLocation(mLocation, false);
106215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            } catch (RemoteException e) {
106315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Log.e(TAG, "RemoteException calling reportLocation");
106415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1067fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        mLastFixTime = System.currentTimeMillis();
1068fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        // report time to first fix
1069fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        if (mTTFF == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1070fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            mTTFF = (int)(mLastFixTime - mFixRequestTime);
1071f4dffd8a45386b5a5f0e6de4f30facc9eaac4001The Android Open Source Project            if (DEBUG) Log.d(TAG, "TTFF: " + mTTFF);
1072fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson
1073fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            // notify status listeners
1074fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            synchronized(mListeners) {
1075fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                int size = mListeners.size();
1076fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                for (int i = 0; i < size; i++) {
1077fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    Listener listener = mListeners.get(i);
1078fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    try {
1079f4dffd8a45386b5a5f0e6de4f30facc9eaac4001The Android Open Source Project                        listener.mListener.onFirstFix(mTTFF);
1080fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    } catch (RemoteException e) {
1081fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        Log.w(TAG, "RemoteException in stopNavigating");
1082fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        mListeners.remove(listener);
1083fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        // adjust for size of list changing
1084fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        size--;
1085fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    }
1086fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                }
1087fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            }
1088fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        }
1089fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson
109003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        if (mSingleShot) {
109103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            stopNavigating();
109203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
109315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mStarted && mStatus != LocationProvider.AVAILABLE) {
1094d53ba017ee2381383b4bb4d92e6e0e661431660fMike Lockwood            // we want to time out if we do not receive a fix
1095b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood            // within the time out and we are requesting infrequent fixes
109604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {
1097b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood                mAlarmManager.cancel(mTimeoutIntent);
1098b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood            }
1099b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is receiving fixes.
110100b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
110200b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
110415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.AVAILABLE, mSvCount);
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
110629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
110703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood       if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted && mFixInterval > 1000) {
1108d53ba017ee2381383b4bb4d92e6e0e661431660fMike Lockwood            if (DEBUG) Log.d(TAG, "got fix, hibernating");
11090632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            hibernate();
111029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        }
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   }
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our status
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportStatus(int status) {
1117b8d9033d9928209e68518c4b12fea74187ddb382Mike Lockwood        if (DEBUG) Log.v(TAG, "reportStatus status: " + status);
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11192e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
11202e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            boolean wasNavigating = mNavigating;
1121dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood
1122cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            switch (status) {
1123cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_SESSION_BEGIN:
1124cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mNavigating = true;
1125271f9f172b241607b1ed39a7709c3ed47ee5dee7Mike Lockwood                    mEngineOn = true;
1126cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1127cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_SESSION_END:
1128cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mNavigating = false;
1129cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1130cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_ENGINE_ON:
1131cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mEngineOn = true;
1132cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1133cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_ENGINE_OFF:
1134cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mEngineOn = false;
1135271f9f172b241607b1ed39a7709c3ed47ee5dee7Mike Lockwood                    mNavigating = false;
1136cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1137cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            }
1138cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood
1139dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood            if (wasNavigating != mNavigating) {
1140dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                int size = mListeners.size();
1141dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                for (int i = 0; i < size; i++) {
1142dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    Listener listener = mListeners.get(i);
1143dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    try {
1144dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        if (mNavigating) {
1145dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            listener.mListener.onGpsStarted();
1146dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        } else {
1147dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            listener.mListener.onGpsStopped();
1148dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        }
1149dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    } catch (RemoteException e) {
1150dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        Log.w(TAG, "RemoteException in reportStatus");
1151dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        mListeners.remove(listener);
1152dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        // adjust for size of list changing
1153dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        size--;
1154dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    }
1155dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                }
1156dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood
11572e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
1158dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    // update battery stats
1159dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    for (int i=mClientUids.size() - 1; i >= 0; i--) {
1160dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        int uid = mClientUids.keyAt(i);
1161dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        if (mNavigating) {
1162dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            mBatteryStats.noteStartGps(uid);
1163dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        } else {
1164dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            mBatteryStats.noteStopGps(uid);
1165dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        }
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11672e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
11682e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in reportStatus");
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1171dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                // send an intent to notify that the GPS has been enabled or disabled.
117200b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood                Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
117300b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood                intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
1174dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                mContext.sendBroadcast(intent);
11752f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update SV info
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportSvStatus() {
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(mListeners) {
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int size = mListeners.size();
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < size; i++) {
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Listener listener = mListeners.get(i);
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs,
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSvElevations, mSvAzimuths, mSvMasks[EPHEMERIS_MASK],
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK]);
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.w(TAG, "RemoteException in reportSvInfo");
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mListeners.remove(listener);
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // adjust for size of list changing
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    size--;
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
120329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) {
120429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            Log.v(TAG, "SV count: " + svCount +
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) +
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK]));
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < svCount; i++) {
120829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                Log.v(TAG, "sv: " + mSvs[i] +
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " snr: " + (float)mSnrs[i]/10 +
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " elev: " + mSvElevations[i] +
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " azimuth: " + mSvAzimuths[i] +
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " E") +
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " A") +
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U"));
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12180881f4f9339febee85c9ab4cba69970ac5cbde55Kevin.KY Tsai        // return number of sets used in fix instead of total
12190881f4f9339febee85c9ab4cba69970ac5cbde55Kevin.KY Tsai        updateStatus(mStatus, Integer.bitCount(mSvMasks[USED_FOR_FIX_MASK]));
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
122115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
122204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is no longer receiving fixes.
122400b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
122500b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
122715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
123058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
123158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    /**
1232e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood     * called from native code to update AGPS status
123358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood     */
1234e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private void reportAGpsStatus(int type, int status) {
123558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        switch (status) {
1236e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_REQUEST_AGPS_DATA_CONN:
1237b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
12382acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                // Set mAGpsDataConnectionState before calling startUsingNetworkFeature
12392acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                //  to avoid a race condition with handleUpdateNetworkState()
12402acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
12412acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                int result = mConnMgr.startUsingNetworkFeature(
124258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                        ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
124358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                if (result == Phone.APN_ALREADY_ACTIVE) {
12442d4d1bf14b531de9d4238b1e41b53c77f8976405Mike Lockwood                    if (DEBUG) Log.d(TAG, "Phone.APN_ALREADY_ACTIVE");
1245b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    if (mAGpsApn != null) {
1246b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        native_agps_data_conn_open(mAGpsApn);
1247b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
1248b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    } else {
1249b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        Log.e(TAG, "mAGpsApn not set when receiving Phone.APN_ALREADY_ACTIVE");
12502acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
1251b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        native_agps_data_conn_failed();
1252b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    }
125358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else if (result == Phone.APN_REQUEST_STARTED) {
12544a7b65e0d544ef1feff8e1e5789f469f89ebb85cMike Lockwood                    if (DEBUG) Log.d(TAG, "Phone.APN_REQUEST_STARTED");
12552acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                    // Nothing to do here
125658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else {
1257b8d9033d9928209e68518c4b12fea74187ddb382Mike Lockwood                    if (DEBUG) Log.d(TAG, "startUsingNetworkFeature failed");
12582acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
1259e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_failed();
126058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
126158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1262e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_RELEASE_AGPS_DATA_CONN:
1263b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
1264e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
126558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                    mConnMgr.stopUsingNetworkFeature(
126658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                            ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
1267e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_closed();
1268e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
126958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
127058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1271e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONNECTED:
1272b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
127358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1274e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_DONE:
1275b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
127658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1277e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_FAILED:
1278b6e5fa895c03eeefaa810eaceb498254096c093dMike Lockwood                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
127958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
128058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        }
128158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    }
128258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1283b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    /**
1284b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood     * called from native code to report NMEA data received
1285b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood     */
1286f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood    private void reportNmea(long timestamp) {
1287b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood        synchronized(mListeners) {
1288b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            int size = mListeners.size();
1289b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            if (size > 0) {
1290b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                // don't bother creating the String if we have no listeners
1291f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood                int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
1292b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                String nmea = new String(mNmeaBuffer, 0, length);
1293b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood
1294b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                for (int i = 0; i < size; i++) {
1295b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    Listener listener = mListeners.get(i);
1296b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    try {
1297b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        listener.mListener.onNmeaReceived(timestamp, nmea);
1298b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    } catch (RemoteException e) {
1299b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        Log.w(TAG, "RemoteException in reportNmea");
1300b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        mListeners.remove(listener);
1301b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        // adjust for size of list changing
1302b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        size--;
1303b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    }
1304b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                }
1305b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            }
1306b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood        }
1307b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    }
1308b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood
130962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    /**
131004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood     * called from native code to inform us what the GPS engine capabilities are
131104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood     */
131204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private void setEngineCapabilities(int capabilities) {
131304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood        mEngineCapabilities = capabilities;
13149b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood
13159b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood        if (!hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME) && !mPeriodicTimeInjection) {
13169b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            mPeriodicTimeInjection = true;
13179b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood            requestUtcTime();
13189b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood        }
131904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    }
132004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
132104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    /**
132262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood     * called from native code to request XTRA data
132362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood     */
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void xtraDownloadRequest() {
1325f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
132698e48691f738680fe59e7383a41458e7337daccdMike Lockwood        sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
132922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    //=============================================================
133022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // NI Client support
13311e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    //=============================================================
133222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
13331e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        // Sends a response for an NI reqeust to HAL.
13341e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        public boolean sendNiResponse(int notificationId, int userResponse)
13351e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        {
13361e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            // TODO Add Permission check
13371e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13381e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            StringBuilder extrasBuf = new StringBuilder();
13391e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13401e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
13411e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                    ", response: " + userResponse);
13421e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            native_send_ni_response(notificationId, userResponse);
13431e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            return true;
13441e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
134522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    };
134622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
134722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    public INetInitiatedListener getNetInitiatedListener() {
134822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        return mNetInitiatedListener;
134922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    }
135022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
135122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // Called by JNI function to report an NI request.
13521e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    public void reportNiNotification(
13531e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int notificationId,
13541e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int niType,
13551e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int notifyFlags,
13561e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int timeout,
13571e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int defaultResponse,
13581e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String requestorId,
13591e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String text,
13601e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int requestorIdEncoding,
13611e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int textEncoding,
13621e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String extras  // Encoded extra data
136322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        )
13641e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    {
13651e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Log.i(TAG, "reportNiNotification: entered");
13661e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Log.i(TAG, "notificationId: " + notificationId +
13671e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", niType: " + niType +
13681e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", notifyFlags: " + notifyFlags +
13691e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", timeout: " + timeout +
13701e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", defaultResponse: " + defaultResponse);
13711e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13721e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Log.i(TAG, "requestorId: " + requestorId +
13731e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", text: " + text +
13741e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", requestorIdEncoding: " + requestorIdEncoding +
13751e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                ", textEncoding: " + textEncoding);
13761e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13771e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        GpsNiNotification notification = new GpsNiNotification();
13781e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13791e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.notificationId = notificationId;
13801e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.niType = niType;
13811e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
13821e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
13831e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
13841e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.timeout = timeout;
13851e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.defaultResponse = defaultResponse;
13861e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.requestorId = requestorId;
13871e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.text = text;
13881e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.requestorIdEncoding = requestorIdEncoding;
13891e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.textEncoding = textEncoding;
13901e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13911e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        // Process extras, assuming the format is
13921e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        // one of more lines of "key = value"
13931e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Bundle bundle = new Bundle();
13941e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13951e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        if (extras == null) extras = "";
13961e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        Properties extraProp = new Properties();
13971e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
13981e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        try {
1399104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey            extraProp.load(new StringReader(extras));
14001e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
14011e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        catch (IOException e)
14021e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        {
14031e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
14041e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
14051e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14061e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        for (Entry<Object, Object> ent : extraProp.entrySet())
14071e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        {
14081e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            bundle.putString((String) ent.getKey(), (String) ent.getValue());
14091e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
14101e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14111e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        notification.extras = bundle;
14121e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14131e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        mNIHandler.handleNiNotification(notification);
14141e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
14151e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14161e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    /**
14171e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * Called from native code to request set id info.
14181e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * We should be careful about receiving null string from the TelephonyManager,
14191e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * because sending null String to JNI function would cause a crash.
14201e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     */
14211e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14221e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void requestSetID(int flags) {
14231e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        TelephonyManager phone = (TelephonyManager)
14241e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                mContext.getSystemService(Context.TELEPHONY_SERVICE);
14251e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        int    type = AGPS_SETID_TYPE_NONE;
14261e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        String data = "";
14271e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14281e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
14291e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String data_temp = phone.getSubscriberId();
14301e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            if (data_temp == null) {
14311e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework does not have the SIM card ready.
14321e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else {
14331e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework has the SIM card.
14341e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                data = data_temp;
14351e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                type = AGPS_SETID_TYPE_IMSI;
14361e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            }
14371e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
14381e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
14391e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            String data_temp = phone.getLine1Number();
14401e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            if (data_temp == null) {
14411e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework does not have the SIM card ready.
14421e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            } else {
14431e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                // This means the framework has the SIM card.
14441e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                data = data_temp;
14451e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                type = AGPS_SETID_TYPE_MSISDN;
14461e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            }
14471e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
14481e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        native_agps_set_id(type, data);
14491e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
14501e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14511e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    /**
14529b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood     * Called from native code to request utc time info
14539b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood     */
14549b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood
14559b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    private void requestUtcTime() {
14569b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood        sendMessage(INJECT_NTP_TIME, 0, null);
14579b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    }
14589b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood
14599b9fb5cc08eaa0b66a80eba2f03168531544f65aMike Lockwood    /**
14601e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     * Called from native code to request reference location info
14611e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja     */
14621e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
14631e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private void requestRefLocation(int flags) {
14641e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        TelephonyManager phone = (TelephonyManager)
14651e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                mContext.getSystemService(Context.TELEPHONY_SERVICE);
14661e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        if (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
14671e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation();
1468edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood            if ((gsm_cell != null) && (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) &&
1469edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                    (phone.getNetworkOperator() != null) &&
1470edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                        (phone.getNetworkOperator().length() > 3)) {
14711e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                int type;
14721e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0,3));
14731e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3));
1474edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                int networkType = phone.getNetworkType();
1475edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                if (networkType == TelephonyManager.NETWORK_TYPE_UMTS
1476edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                    || networkType == TelephonyManager.NETWORK_TYPE_HSDPA
1477edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                    || networkType == TelephonyManager.NETWORK_TYPE_HSUPA
1478edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                    || networkType == TelephonyManager.NETWORK_TYPE_HSPA) {
14791e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                    type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
1480edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                } else {
14811e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                    type = AGPS_REF_LOCATION_TYPE_GSM_CELLID;
1482edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood                }
14831e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                native_agps_set_ref_location_cellid(type, mcc, mnc,
14841e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                        gsm_cell.getLac(), gsm_cell.getCid());
1485edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood            } else {
14861e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja                Log.e(TAG,"Error getting cell location info.");
1487edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood            }
14881e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja        }
1489edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood        else {
14901e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            Log.e(TAG,"CDMA not supported.");
1491edc0f3876ce6e14f0ce35ad950c55031694fd4f8Mike Lockwood        }
14921e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    }
149322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
149498e48691f738680fe59e7383a41458e7337daccdMike Lockwood    private void sendMessage(int message, int arg, Object obj) {
149598e48691f738680fe59e7383a41458e7337daccdMike Lockwood        // hold a wake lock while messages are pending
149698e48691f738680fe59e7383a41458e7337daccdMike Lockwood        synchronized (mWakeLock) {
149798e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mPendingMessageBits |= (1 << message);
149898e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mWakeLock.acquire();
149998e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.removeMessages(message);
150098e48691f738680fe59e7383a41458e7337daccdMike Lockwood            Message m = Message.obtain(mHandler, message);
150198e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.arg1 = arg;
150298e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.obj = obj;
150398e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.sendMessage(m);
150498e48691f738680fe59e7383a41458e7337daccdMike Lockwood        }
150598e48691f738680fe59e7383a41458e7337daccdMike Lockwood    }
150698e48691f738680fe59e7383a41458e7337daccdMike Lockwood
150762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private final class ProviderHandler extends Handler {
150862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        @Override
15094a7b65e0d544ef1feff8e1e5789f469f89ebb85cMike Lockwood        public void handleMessage(Message msg) {
151098e48691f738680fe59e7383a41458e7337daccdMike Lockwood            int message = msg.what;
151198e48691f738680fe59e7383a41458e7337daccdMike Lockwood            switch (message) {
151262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case ENABLE:
151362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    if (msg.arg1 == 1) {
151462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                        handleEnable();
151562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    } else {
151662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                        handleDisable();
15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
151862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
151962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case ENABLE_TRACKING:
152062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleEnableLocationTracking(msg.arg1 == 1);
152162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
152203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                case REQUEST_SINGLE_SHOT:
152303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    handleRequestSingleShot();
152403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    break;
152562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case UPDATE_NETWORK_STATE:
152662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleUpdateNetworkState(msg.arg1, (NetworkInfo)msg.obj);
152762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
152862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case INJECT_NTP_TIME:
152962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleInjectNtpTime();
153062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
153162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case DOWNLOAD_XTRA_DATA:
15321a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood                    if (mSupportsXtra) {
153362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                        handleDownloadXtraData();
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
153562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
153662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case UPDATE_LOCATION:
153762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleUpdateLocation((Location)msg.obj);
153862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
153962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case ADD_LISTENER:
154062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleAddListener(msg.arg1);
154162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
154262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case REMOVE_LISTENER:
154362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleRemoveListener(msg.arg1);
154462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
154698e48691f738680fe59e7383a41458e7337daccdMike Lockwood            // release wake lock if no messages are pending
154798e48691f738680fe59e7383a41458e7337daccdMike Lockwood            synchronized (mWakeLock) {
154898e48691f738680fe59e7383a41458e7337daccdMike Lockwood                mPendingMessageBits &= ~(1 << message);
154998e48691f738680fe59e7383a41458e7337daccdMike Lockwood                if (message == ADD_LISTENER || message == REMOVE_LISTENER) {
155098e48691f738680fe59e7383a41458e7337daccdMike Lockwood                    mPendingListenerMessages--;
155198e48691f738680fe59e7383a41458e7337daccdMike Lockwood                }
155298e48691f738680fe59e7383a41458e7337daccdMike Lockwood                if (mPendingMessageBits == 0 && mPendingListenerMessages == 0) {
155398e48691f738680fe59e7383a41458e7337daccdMike Lockwood                    mWakeLock.release();
155498e48691f738680fe59e7383a41458e7337daccdMike Lockwood                }
155598e48691f738680fe59e7383a41458e7337daccdMike Lockwood            }
15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
155762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    };
15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
155989096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private final class GpsLocationProviderThread extends Thread {
156089096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood
156189096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        public GpsLocationProviderThread() {
156289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            super("GpsLocationProvider");
156389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        }
156489096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood
156589096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        public void run() {
156689096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
156789096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            initialize();
156889096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            Looper.prepare();
156989096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            mHandler = new ProviderHandler();
157089096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            // signal when we are initialized and ready to go
157189096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            mInitializedLatch.countDown();
157289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            Looper.loop();
157389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        }
15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for GPS SV statistics
15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int MAX_SVS = 32;
15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int EPHEMERIS_MASK = 0;
15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int ALMANAC_MASK = 1;
15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int USED_FOR_FIX_MASK = 2;
15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // preallocated arrays, to avoid memory allocation in reportStatus()
15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvs[] = new int[MAX_SVS];
15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSnrs[] = new float[MAX_SVS];
15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvElevations[] = new float[MAX_SVS];
15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvAzimuths[] = new float[MAX_SVS];
15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvMasks[] = new int[3];
15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvCount;
1589b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    // preallocated to avoid memory allocation in reportNmea()
1590b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    private byte[] mNmeaBuffer = new byte[120];
15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static { class_init_native(); }
15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native void class_init_native();
15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native boolean native_is_supported();
15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_init();
15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_cleanup();
159804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private native boolean native_set_position_mode(int mode, int recurrence, int min_interval,
159904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            int preferred_accuracy, int preferred_time);
160004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private native boolean native_start();
16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_stop();
16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_delete_aiding_data(int flags);
16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // returns number of SVs
16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // mask[0] is ephemeris mask and mask[1] is almanac mask
16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native int native_read_sv_status(int[] svs, float[] snrs,
16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] elevations, float[] azimuths, int[] masks);
1607f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood    private native int native_read_nmea(byte[] buffer, int bufferSize);
1608d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood    private native void native_inject_location(double latitude, double longitude, float accuracy);
1609d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood
16103c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    // XTRA Support
16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_time(long time, long timeReference, int uncertainty);
16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_supports_xtra();
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_xtra_data(byte[] data, int length);
1614105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
16153c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    // DEBUG Support
16163c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    private native String native_get_internal_state();
16173c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger
16183c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    // AGPS Support
1619e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_open(String apn);
1620e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_closed();
1621e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_failed();
16221e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private native void native_agps_ni_message(byte [] msg, int length);
1623a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood    private native void native_set_agps_server(int type, String hostname, int port);
162422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
162522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // Network-initiated (NI) Support
162622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private native void native_send_ni_response(int notificationId, int userResponse);
16271e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja
16281e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    // AGPS ril suport
16291e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
16301e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja            int lac, int cid);
16311e84da822e7aa4d494b31c8759917d2751611f84Miguel Torroja    private native void native_agps_set_id(int type, String setid);
163250130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood
163350130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood    private native void native_update_network_state(boolean connected, int type,
163450130bbc884a7ad7db39dbc4f54e76e8be87761fMike Lockwood            boolean roaming, String extraInfo);
16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1636