GpsLocationProvider.java revision 2acfd34ccbd39258422333c9c66c586297c97683
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1700b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwoodpackage com.android.server.location;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1929c84340a14e70419449628ab193d11b7a609e9aMike Lockwoodimport android.app.AlarmManager;
2029c84340a14e70419449628ab193d11b7a609e9aMike Lockwoodimport android.app.PendingIntent;
21105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.content.BroadcastReceiver;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
24105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport android.content.IntentFilter;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Criteria;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.IGpsStatusListener;
2715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwoodimport android.location.IGpsStatusProvider;
284e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwoodimport android.location.ILocationManager;
2922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport android.location.INetInitiatedListener;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Location;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationManager;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationProvider;
3358bda987665af759c379cd494ff4873ac61acf29Mike Lockwoodimport android.net.ConnectivityManager;
3403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwoodimport android.net.NetworkInfo;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.SntpClient;
3663aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwoodimport android.os.Binder;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
3862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwoodimport android.os.Handler;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
4062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwoodimport android.os.Looper;
4162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwoodimport android.os.Message;
420528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwoodimport android.os.PowerManager;
4362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwoodimport android.os.Process;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
452f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport android.os.ServiceManager;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
477e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackbornimport android.os.WorkSource;
48bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwoodimport android.provider.Settings;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
502f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport android.util.SparseIntArray;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
522f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport com.android.internal.app.IBatteryStats;
53105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport com.android.internal.telephony.Phone;
5422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport com.android.internal.location.GpsNetInitiatedHandler;
5522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
56105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileInputStream;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
6022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport java.io.StringBufferInputStream;
61105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport java.net.InetAddress;
62105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport java.net.UnknownHostException;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
64f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwoodimport java.util.Date;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Properties;
6622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport java.util.Map.Entry;
6789096317104722219f73a5c3cc424e6e98c90a61Mike Lockwoodimport java.util.concurrent.CountDownLatch;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A GPS implementation of LocationProvider used by LocationManager.
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
7489096317104722219f73a5c3cc424e6e98c90a61Mike Lockwoodpublic class GpsLocationProvider implements LocationProviderInterface {
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "GpsLocationProvider";
7729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
78f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato    private static final boolean DEBUG = false;
7929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private static final boolean VERBOSE = false;
8062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
81105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    // these need to match GpsPositionMode enum in gps.h
82105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_STANDALONE = 0;
83105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_MS_BASED = 1;
84105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
85105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
8604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // these need to match GpsPositionRecurrence enum in gps.h
8704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_POSITION_RECURRENCE_PERIODIC = 0;
8804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_POSITION_RECURRENCE_SINGLE = 1;
8904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these need to match GpsStatusValue defines in gps.h
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_NONE = 0;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_SESSION_BEGIN = 1;
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_SESSION_END = 2;
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_ENGINE_ON = 3;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_ENGINE_OFF = 4;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
97e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // these need to match GpsApgsStatusValue defines in gps.h
98e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    /** AGPS status event values. */
99e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
100e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
101e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONNECTED = 3;
102e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONN_DONE = 4;
103e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
10458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these need to match GpsLocationFlags enum in gps.h
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_INVALID = 0;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_LAT_LONG = 1;
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_ALTITUDE = 2;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_SPEED = 4;
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_BEARING = 8;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_ACCURACY = 16;
112e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
113e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood// IMPORTANT - the GPS_DELETE_* symbols here must match constants in gps.h
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_EPHEMERIS = 0x0001;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_ALMANAC = 0x0002;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_POSITION = 0x0004;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_TIME = 0x0008;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_IONO = 0x0010;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_UTC = 0x0020;
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_HEALTH = 0x0040;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SVDIR = 0x0080;
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SVSTEER = 0x0100;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SADATA = 0x0200;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_RTI = 0x0400;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_ALL = 0xFFFF;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // The GPS_CAPABILITY_* flags must match the values in gps.h
12904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_SCHEDULING = 0x0000001;
13004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_MSB = 0x0000002;
13104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_MSA = 0x0000004;
13204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
13304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
13404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
135e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // these need to match AGpsType enum in gps.h
136e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_TYPE_SUPL = 1;
137e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_TYPE_C2K = 2;
138e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
139e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // for mAGpsDataConnectionState
140e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
141e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_OPENING = 1;
142e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_OPEN = 2;
14358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
14462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    // Handler messages
14562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int CHECK_LOCATION = 1;
14662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int ENABLE = 2;
14762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int ENABLE_TRACKING = 3;
14862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int UPDATE_NETWORK_STATE = 4;
14962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int INJECT_NTP_TIME = 5;
15062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int DOWNLOAD_XTRA_DATA = 6;
15162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int UPDATE_LOCATION = 7;
15262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int ADD_LISTENER = 8;
15362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private static final int REMOVE_LISTENER = 9;
15403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private static final int REQUEST_SINGLE_SHOT = 10;
15562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String PROPERTIES_FILE = "/etc/gps.conf";
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mLocationFlags = LOCATION_INVALID;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current status
16115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time for last status update
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mStatusUpdateTime = SystemClock.elapsedRealtime();
165d53ba017ee2381383b4bb4d92e6e0e661431660fMike Lockwood
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // turn off GPS fix icon if we haven't received a fix in 10 seconds
16704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final long RECENT_FIX_TIMEOUT = 10 * 1000;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1690632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    // stop trying if we do not receive a fix within 60 seconds
17004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private static final int NO_FIX_TIMEOUT = 60 * 1000;
1710632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we are enabled
17389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private volatile boolean mEnabled;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we have network connectivity
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNetworkAvailable;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    // flags to trigger NTP or XTRA data download when network becomes available
17962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    // initialized to true so we do NTP and XTRA when the network comes up after booting
18062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private boolean mInjectNtpTimePending = true;
1815723dfe8c87d0887b8926f43637ed300466890d2Mike Lockwood    private boolean mDownloadXtraDataPending = false;
18262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if GPS is navigating
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNavigating;
185cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood
186cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood    // true if GPS engine is on
187cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood    private boolean mEngineOn;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // requested frequency of fixes, in milliseconds
19004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private int mFixInterval = 1000;
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we started navigation
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mStarted;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    // true if single shot request is in progress
19603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private boolean mSingleShot;
19703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
19804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    // capabilities of the GPS engine
19904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private int mEngineCapabilities;
20004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
2011a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood    // true if XTRA is supported
2021a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood    private boolean mSupportsXtra;
2031a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for calculating time to first fix
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mFixRequestTime = 0;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time to first fix for most recent session
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mTTFF = 0;
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time we received our last fix
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mLastFixTime;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private int mPositionMode;
21204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // properties loaded from PROPERTIES_FILE
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Properties mProperties;
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String mNtpServer;
216734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private String mSuplServerHost;
217734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private int mSuplServerPort;
218734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private String mC2KServerHost;
219734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private int mC2KServerPort;
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final Context mContext;
22215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final ILocationManager mLocationManager;
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Bundle mLocationExtras = new Bundle();
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<Listener> mListeners = new ArrayList<Listener>();
22662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
22789096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    // GpsLocationProvider's handler thread
22889096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private final Thread mThread;
22989096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    // Handler for processing events in mThread.
23062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private Handler mHandler;
23189096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    // Used to signal when our main thread has initialized everything
23289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private final CountDownLatch mInitializedLatch = new CountDownLatch(1);
233105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
234e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private String mAGpsApn;
235e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private int mAGpsDataConnectionState;
2362f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final ConnectivityManager mConnMgr;
23722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private final GpsNetInitiatedHandler mNIHandler;
2382f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
2390528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    // Wakelocks
2400528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final static String WAKELOCK_KEY = "GpsLocationProvider";
2410528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final PowerManager.WakeLock mWakeLock;
24298e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // bitfield of pending messages to our Handler
24398e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // used only for messages that cannot have multiple instances queued
24498e48691f738680fe59e7383a41458e7337daccdMike Lockwood    private int mPendingMessageBits;
24598e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // separate counter for ADD_LISTENER and REMOVE_LISTENER messages,
24698e48691f738680fe59e7383a41458e7337daccdMike Lockwood    // which might have multiple instances queued
24798e48691f738680fe59e7383a41458e7337daccdMike Lockwood    private int mPendingListenerMessages;
2480528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
24929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    // Alarms
25029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
2510632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
25229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final AlarmManager mAlarmManager;
25329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final PendingIntent mWakeupIntent;
2540632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final PendingIntent mTimeoutIntent;
25529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
2562f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final IBatteryStats mBatteryStats;
2572f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final SparseIntArray mClientUids = new SparseIntArray();
258105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // how often to request NTP time, in milliseconds
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current setting 4 hours
261f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood    private static final long NTP_INTERVAL = 4*60*60*1000;
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // how long to wait if we have a network error in NTP or XTRA downloading
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current setting - 5 minutes
264f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood    private static final long RETRY_INTERVAL = 5*60*1000;
265f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood
266f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood    // to avoid injecting bad NTP time, we reject any time fixes that differ from system time
267f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood    // by more than 5 minutes.
268f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood    private static final long MAX_NTP_SYSTEM_TIME_OFFSET = 5*60*1000;
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
27115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
27215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
27315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
27415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
27515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
27615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            synchronized(mListeners) {
27715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
27815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
27915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size; i++) {
28015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
28115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
28215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        // listener already added
28315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        return;
28415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
28515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
28615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
28715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = new Listener(listener);
28815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                binder.linkToDeath(l, 0);
28915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                mListeners.add(l);
29015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
29115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
29215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
29315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void removeGpsStatusListener(IGpsStatusListener listener) {
29415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
29515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
29615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
29715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
29815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            synchronized(mListeners) {
29915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
30015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = null;
30115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
30215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size && l == null; i++) {
30315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
30415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
30515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        l = test;
30615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
30715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
30815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
30915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                if (l != null) {
31015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    mListeners.remove(l);
31115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    binder.unlinkToDeath(l, 0);
31215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
31315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
31415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
31515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    };
31615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
31715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    public IGpsStatusProvider getGpsStatusProvider() {
31815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        return mGpsStatusProvider;
31915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
32015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
32129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
322105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        @Override public void onReceive(Context context, Intent intent) {
323105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            String action = intent.getAction();
324105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
32529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (action.equals(ALARM_WAKEUP)) {
32629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_WAKEUP");
32703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                startNavigating(false);
3280632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            } else if (action.equals(ALARM_TIMEOUT)) {
3290632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");
3300632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                hibernate();
331105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
332105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
33329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    };
334105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean isSupported() {
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_is_supported();
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3394e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    public GpsLocationProvider(Context context, ILocationManager locationManager) {
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
34115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mLocationManager = locationManager;
34279e642e8ed75033eacc461633a8f4cd5157d25dfMike Lockwood        mNIHandler = new GpsNetInitiatedHandler(context);
34363598a0619776b421f27cd12fb29eb83dc327997Mike Lockwood
34463598a0619776b421f27cd12fb29eb83dc327997Mike Lockwood        mLocation.setExtras(mLocationExtras);
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3460528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // Create a wake lock
3470528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
3480528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
34998e48691f738680fe59e7383a41458e7337daccdMike Lockwood        mWakeLock.setReferenceCounted(false);
3500528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
35129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
35229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
3530632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
35429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
35558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
35658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
3572f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        // Battery statistics service to be notified when GPS turns on or off
3582f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
3592f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProperties = new Properties();
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            File file = new File(PROPERTIES_FILE);
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            FileInputStream stream = new FileInputStream(file);
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProperties.load(stream);
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stream.close();
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNtpServer = mProperties.getProperty("NTP_SERVER", null);
367e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
368734d6031a662a275ec68627bd1258159041d44deMike Lockwood            mSuplServerHost = mProperties.getProperty("SUPL_HOST");
369e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            String portString = mProperties.getProperty("SUPL_PORT");
370734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mSuplServerHost != null && portString != null) {
371105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                try {
372734d6031a662a275ec68627bd1258159041d44deMike Lockwood                    mSuplServerPort = Integer.parseInt(portString);
373105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                } catch (NumberFormatException e) {
374e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
375e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                }
376e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            }
377e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
378734d6031a662a275ec68627bd1258159041d44deMike Lockwood            mC2KServerHost = mProperties.getProperty("C2K_HOST");
379e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            portString = mProperties.getProperty("C2K_PORT");
380734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mC2KServerHost != null && portString != null) {
381e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                try {
382734d6031a662a275ec68627bd1258159041d44deMike Lockwood                    mC2KServerPort = Integer.parseInt(portString);
383e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                } catch (NumberFormatException e) {
384e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse C2K_PORT: " + portString);
385105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                }
386105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
39062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
39189096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        // wait until we are fully initialized before returning
39289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        mThread = new GpsLocationProviderThread();
39389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        mThread.start();
39489096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        while (true) {
39589096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            try {
39689096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood                mInitializedLatch.await();
39789096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood                break;
39889096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            } catch (InterruptedException e) {
39989096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood                Thread.currentThread().interrupt();
40089096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            }
40189096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        }
40262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
40362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
40462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void initialize() {
40562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        // register our receiver on our thread rather than the main thread
40662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        IntentFilter intentFilter = new IntentFilter();
40762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        intentFilter.addAction(ALARM_WAKEUP);
40862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        intentFilter.addAction(ALARM_TIMEOUT);
40962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mContext.registerReceiver(mBroadcastReciever, intentFilter);
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
413d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood     * Returns the name of this provider.
414d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood     */
415d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    public String getName() {
416d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        return LocationManager.GPS_PROVIDER;
417d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    }
418d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood
419d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    /**
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to a
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * data network (e.g., the Internet), false otherwise.
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresNetwork() {
424a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood        return true;
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
42703d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood    public void updateNetworkState(int state, NetworkInfo info) {
42898e48691f738680fe59e7383a41458e7337daccdMike Lockwood        sendMessage(UPDATE_NETWORK_STATE, state, info);
42962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
43062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
43162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleUpdateNetworkState(int state, NetworkInfo info) {
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNetworkAvailable = (state == LocationProvider.AVAILABLE);
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
434f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) {
43503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            Log.d(TAG, "updateNetworkState " + (mNetworkAvailable ? "available" : "unavailable")
43603d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                + " info: " + info);
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
43803d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood
43903d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood        if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL
44003d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
44103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            String apnName = info.getExtraInfo();
44203d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            if (mNetworkAvailable && apnName != null && apnName.length() > 0) {
44303d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsApn = apnName;
44403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                if (DEBUG) Log.d(TAG, "call native_agps_data_conn_open");
44503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                native_agps_data_conn_open(apnName);
44603d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
44703d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            } else {
44803d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                if (DEBUG) Log.d(TAG, "call native_agps_data_conn_failed");
44903d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsApn = null;
45003d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
45103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                native_agps_data_conn_failed();
45203d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            }
45303d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood        }
45403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood
45562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (mNetworkAvailable) {
45662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (mInjectNtpTimePending) {
45798e48691f738680fe59e7383a41458e7337daccdMike Lockwood                sendMessage(INJECT_NTP_TIME, 0, null);
45862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            }
45962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (mDownloadXtraDataPending) {
46098e48691f738680fe59e7383a41458e7337daccdMike Lockwood                sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
46162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            }
46262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
46362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
46462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
46562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleInjectNtpTime() {
46662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (!mNetworkAvailable) {
46762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            // try again when network is up
46862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mInjectNtpTimePending = true;
46962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            return;
47062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
47162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mInjectNtpTimePending = false;
47262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
47362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        SntpClient client = new SntpClient();
47462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        long delay;
47562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
47662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (client.requestTime(mNtpServer, 10000)) {
47762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            long time = client.getNtpTime();
47862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            long timeReference = client.getNtpTimeReference();
47962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            int certainty = (int)(client.getRoundTripTime()/2);
48062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            long now = System.currentTimeMillis();
48162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
48262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            Log.d(TAG, "NTP server returned: "
48362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    + time + " (" + new Date(time)
48462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    + ") reference: " + timeReference
48562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    + " certainty: " + certainty
4861879d284bf3dd704dbc8c95aad262ebbe3c3c0a4Mike Lockwood                    + " system time offset: " + (time - now));
48762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
4881879d284bf3dd704dbc8c95aad262ebbe3c3c0a4Mike Lockwood            native_inject_time(time, timeReference, certainty);
48962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            delay = NTP_INTERVAL;
49062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        } else {
49162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (DEBUG) Log.d(TAG, "requestTime failed");
49262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            delay = RETRY_INTERVAL;
49362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
49462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
49562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        // send delayed message for next NTP injection
49698e48691f738680fe59e7383a41458e7337daccdMike Lockwood        // since this is delayed and not urgent we do not hold a wake lock here
49762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mHandler.removeMessages(INJECT_NTP_TIME);
49862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mHandler.sendMessageDelayed(Message.obtain(mHandler, INJECT_NTP_TIME), delay);
49962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
50062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
50162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleDownloadXtraData() {
5025723dfe8c87d0887b8926f43637ed300466890d2Mike Lockwood        if (!mNetworkAvailable) {
50362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            // try again when network is up
50462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mDownloadXtraDataPending = true;
50562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            return;
50662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
50762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        mDownloadXtraDataPending = false;
50862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
50962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
51062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
51162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        byte[] data = xtraDownloader.downloadXtraData();
51262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (data != null) {
51362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            if (DEBUG) {
51462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                Log.d(TAG, "calling native_inject_xtra_data");
51562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            }
51662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            native_inject_xtra_data(data, data.length);
51762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        } else {
51862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            // try again later
51998e48691f738680fe59e7383a41458e7337daccdMike Lockwood            // since this is delayed and not urgent we do not hold a wake lock here
52062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mHandler.removeMessages(DOWNLOAD_XTRA_DATA);
52162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood            mHandler.sendMessageDelayed(Message.obtain(mHandler, DOWNLOAD_XTRA_DATA), RETRY_INTERVAL);
52262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
526fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     * This is called to inform us when another location provider returns a location.
527fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     * Someday we might use this for network location injection to aid the GPS
528fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     */
529fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    public void updateLocation(Location location) {
53098e48691f738680fe59e7383a41458e7337daccdMike Lockwood        sendMessage(UPDATE_LOCATION, 0, location);
53162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
53262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
53362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleUpdateLocation(Location location) {
534d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        if (location.hasAccuracy()) {
535d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood            native_inject_location(location.getLatitude(), location.getLongitude(),
536d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood                    location.getAccuracy());
537d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        }
538fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    }
539fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood
540fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    /**
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to a
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * satellite-based positioning system (e.g., GPS), false
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise.
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresSatellite() {
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to an appropriate
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * cellular network (e.g., to make use of cell tower IDs), false
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise.
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresCell() {
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the use of this provider may result in a
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * monetary charge to the user, false if use is free.  It is up to
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * each provider to give accurate information.
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasMonetaryCost() {
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide altitude
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports altitude
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsAltitude() {
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide speed
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports speed
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsSpeed() {
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide bearing
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports bearing
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsBearing() {
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the power requirement for this provider.
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the power requirement for this provider, as one of the
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * constants Criteria.POWER_REQUIREMENT_*.
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getPowerRequirement() {
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Criteria.POWER_HIGH;
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
60803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood     * Returns true if this provider meets the given criteria,
60903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood     * false otherwise.
61003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood     */
61103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public boolean meetsCriteria(Criteria criteria) {
61203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        return (criteria.getPowerRequirement() != Criteria.POWER_LOW);
61303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
61403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
61503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    /**
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the horizontal accuracy of this provider
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the accuracy of location from this provider, as one
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of the constants Criteria.ACCURACY_*.
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getAccuracy() {
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Criteria.ACCURACY_FINE;
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Enables this provider.  When enabled, calls to getStatus()
6274e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * must be handled.  Hardware may be started up
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the provider is enabled.
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
63062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    public void enable() {
63162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        synchronized (mHandler) {
63298e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(ENABLE, 1, null);
63362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
63462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
63562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
63662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleEnable() {
63762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        if (DEBUG) Log.d(TAG, "handleEnable");
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabled) return;
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnabled = native_init();
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabled) {
6421a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood            mSupportsXtra = native_supports_xtra();
643734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mSuplServerHost != null) {
644734d6031a662a275ec68627bd1258159041d44deMike Lockwood                native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
645734d6031a662a275ec68627bd1258159041d44deMike Lockwood            }
646734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mC2KServerHost != null) {
647734d6031a662a275ec68627bd1258159041d44deMike Lockwood                native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
648734d6031a662a275ec68627bd1258159041d44deMike Lockwood            }
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Failed to enable location provider");
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Disables this provider.  When disabled, calls to getStatus()
6564e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * need not be handled.  Hardware may be shut
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * down while the provider is disabled.
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
65962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    public void disable() {
66062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        synchronized (mHandler) {
66198e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(ENABLE, 0, null);
66262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
66362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
66462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
66562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleDisable() {
66689096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        if (DEBUG) Log.d(TAG, "handleDisable");
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mEnabled) return;
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnabled = false;
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        stopNavigating();
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
672cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood        // do this before releasing wakelock
673cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood        native_cleanup();
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
676d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    public boolean isEnabled() {
677d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        return mEnabled;
678d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    }
679d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getStatus(Bundle extras) {
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras != null) {
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            extras.putInt("satellites", mSvCount);
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatus;
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateStatus(int status, int svCount) {
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (status != mStatus || svCount != mSvCount) {
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatus = status;
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSvCount = svCount;
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationExtras.putInt("satellites", svCount);
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatusUpdateTime = SystemClock.elapsedRealtime();
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public long getStatusUpdateTime() {
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatusUpdateTime;
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void enableLocationTracking(boolean enable) {
70103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        // FIXME - should set a flag here to avoid race conditions with single shot request
70262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        synchronized (mHandler) {
70398e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(ENABLE_TRACKING, (enable ? 1 : 0), null);
70462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        }
70562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
70662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
70762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleEnableLocationTracking(boolean enable) {
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (enable) {
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = 0;
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
71103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            startNavigating(false);
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
71304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
71404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                mAlarmManager.cancel(mWakeupIntent);
71504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                mAlarmManager.cancel(mTimeoutIntent);
71604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            }
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stopNavigating();
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
72103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public boolean requestSingleShotFix() {
72203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        if (mStarted) {
72303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            // cannot do single shot if already navigating
72403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            return false;
72503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
72603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        synchronized (mHandler) {
72703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mHandler.removeMessages(REQUEST_SINGLE_SHOT);
72803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            Message m = Message.obtain(mHandler, REQUEST_SINGLE_SHOT);
72903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mHandler.sendMessage(m);
73003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
73103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        return true;
73203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
73303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
73403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private void handleRequestSingleShot() {
73503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        mTTFF = 0;
73603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        mLastFixTime = 0;
73703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        startNavigating(true);
73803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
73903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
7407e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn    public void setMinTime(long minTime, WorkSource ws) {
741f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) Log.d(TAG, "setMinTime " + minTime);
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (minTime >= 0) {
74404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            mFixInterval = (int)minTime;
74504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
74604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
74704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
74804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                        mFixInterval, 0, 0)) {
74904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                    Log.e(TAG, "set_position_mode failed in setMinTime()");
75004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                }
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7553c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    public String getInternalState() {
7563c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger        return native_get_internal_state();
7573c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    }
7583c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final class Listener implements IBinder.DeathRecipient {
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IGpsStatusListener mListener;
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int mSensors = 0;
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Listener(IGpsStatusListener listener) {
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = listener;
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
769f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato            if (DEBUG) Log.d(TAG, "GPS status listener died");
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(mListeners) {
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mListeners.remove(this);
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
774fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu            if (mListener != null) {
775fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu                mListener.asBinder().unlinkToDeath(this, 0);
776fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu            }
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7802f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    public void addListener(int uid) {
78198e48691f738680fe59e7383a41458e7337daccdMike Lockwood        synchronized (mWakeLock) {
78298e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mPendingListenerMessages++;
7837e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            mWakeLock.acquire();
78498e48691f738680fe59e7383a41458e7337daccdMike Lockwood            Message m = Message.obtain(mHandler, ADD_LISTENER);
78598e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.arg1 = uid;
78698e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.sendMessage(m);
78798e48691f738680fe59e7383a41458e7337daccdMike Lockwood        }
78862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
78962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
79062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleAddListener(int uid) {
7912e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
7922e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mClientUids.indexOfKey(uid) >= 0) {
7932e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                // Shouldn't be here -- already have this uid.
7942e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                Log.w(TAG, "Duplicate add listener for uid " + uid);
7952e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                return;
7962e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            }
7972e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            mClientUids.put(uid, 0);
7982e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mNavigating) {
7992e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
8002e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    mBatteryStats.noteStartGps(uid);
8012e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
8022e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in addListener");
8032e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                }
8042f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
8052f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
8062f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
8072f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8082f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    public void removeListener(int uid) {
80998e48691f738680fe59e7383a41458e7337daccdMike Lockwood        synchronized (mWakeLock) {
81098e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mPendingListenerMessages++;
81198e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mWakeLock.acquire();
81298e48691f738680fe59e7383a41458e7337daccdMike Lockwood            Message m = Message.obtain(mHandler, REMOVE_LISTENER);
81398e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.arg1 = uid;
81498e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.sendMessage(m);
81598e48691f738680fe59e7383a41458e7337daccdMike Lockwood        }
81662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    }
81762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood
81862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void handleRemoveListener(int uid) {
8192e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
8202e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mClientUids.indexOfKey(uid) < 0) {
8212e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                // Shouldn't be here -- don't have this uid.
8222e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                Log.w(TAG, "Unneeded remove listener for uid " + uid);
8232e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                return;
8242e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            }
8252e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            mClientUids.delete(uid);
8262e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mNavigating) {
8272e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
8282e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    mBatteryStats.noteStopGps(uid);
8292e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
8302e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in removeListener");
8312e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                }
8322f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
8332f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
8342f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
8352f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendExtraCommand(String command, Bundle extras) {
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
83863aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        long identity = Binder.clearCallingIdentity();
83963aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        boolean result = false;
84063aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ("delete_aiding_data".equals(command)) {
84263aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood            result = deleteAidingData(extras);
84363aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        } else if ("force_time_injection".equals(command)) {
84498e48691f738680fe59e7383a41458e7337daccdMike Lockwood            sendMessage(INJECT_NTP_TIME, 0, null);
84563aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood            result = true;
84663aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        } else if ("force_xtra_injection".equals(command)) {
8471a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood            if (mSupportsXtra) {
84893bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                xtraDownloadRequest();
84963aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood                result = true;
85093bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            }
85163aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        } else {
85263aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood            Log.w(TAG, "sendExtraCommand: unknown command " + command);
85393bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
85563aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        Binder.restoreCallingIdentity(identity);
85663aa5a6f98b1016863e4f6edd87eb471b28dc28fMike Lockwood        return result;
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean deleteAidingData(Bundle extras) {
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags;
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras == null) {
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = GPS_DELETE_ALL;
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = 0;
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (flags != 0) {
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_delete_aiding_data(flags);
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
88903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    private void startNavigating(boolean singleShot) {
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStarted) {
89129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (DEBUG) Log.d(TAG, "startNavigating");
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = true;
89303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mSingleShot = singleShot;
89403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mPositionMode = GPS_POSITION_MODE_STANDALONE;
89503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
89603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood             if (Settings.Secure.getInt(mContext.getContentResolver(),
897660bbfcc54d48d5d32e64da683c76b9c372c19b1Mike Lockwood                    Settings.Secure.ASSISTED_GPS_ENABLED, 1) != 0) {
89803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                if (singleShot && hasCapability(GPS_CAPABILITY_MSA)) {
89903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    mPositionMode = GPS_POSITION_MODE_MS_ASSISTED;
9008dc16c27e23dae5bdf65fd2a2ced97c2f645a633Mike Lockwood                } else if (hasCapability(GPS_CAPABILITY_MSB)) {
90103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    mPositionMode = GPS_POSITION_MODE_MS_BASED;
90203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                }
903bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood            }
904bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood
90504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
90604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
90704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                    interval, 0, 0)) {
90804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                mStarted = false;
90904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                Log.e(TAG, "set_position_mode failed in startNavigating()");
91004598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                return;
91104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            }
91204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!native_start()) {
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStarted = false;
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.e(TAG, "native_start failed in startNavigating()");
9150632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                return;
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
91915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
92029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            mFixRequestTime = System.currentTimeMillis();
92104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
92204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
92304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                // and our fix interval is not short
92404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                if (mFixInterval >= NO_FIX_TIMEOUT) {
92504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                    mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
92604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                            SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
92704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                }
9280632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            }
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
93262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private void stopNavigating() {
93329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (DEBUG) Log.d(TAG, "stopNavigating");
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mStarted) {
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = false;
93603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            mSingleShot = false;
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_stop();
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = 0;
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = LOCATION_INVALID;
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
94315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9470632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private void hibernate() {
9480632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        // stop GPS until our next fix interval arrives
9490632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        stopNavigating();
9500632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mTimeoutIntent);
9510632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mWakeupIntent);
9520632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        long now = SystemClock.elapsedRealtime();
9530632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
95404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood                SystemClock.elapsedRealtime() + mFixInterval, mWakeupIntent);
95504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    }
95604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
95704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private boolean hasCapability(int capability) {
95804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood        return ((mEngineCapabilities & capability) != 0);
9590632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    }
9600632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our position.
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportLocation(int flags, double latitude, double longitude, double altitude,
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float speed, float bearing, float accuracy, long timestamp) {
96629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                " timestamp: " + timestamp);
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mLocation) {
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = flags;
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLatitude(latitude);
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLongitude(longitude);
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setTime(timestamp);
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAltitude(altitude);
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAltitude();
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setSpeed(speed);
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeSpeed();
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setBearing(bearing);
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeBearing();
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAccuracy(accuracy);
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAccuracy();
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
99715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            try {
998a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                mLocationManager.reportLocation(mLocation, false);
99915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            } catch (RemoteException e) {
100015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Log.e(TAG, "RemoteException calling reportLocation");
100115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1004fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        mLastFixTime = System.currentTimeMillis();
1005fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        // report time to first fix
1006fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        if (mTTFF == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1007fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            mTTFF = (int)(mLastFixTime - mFixRequestTime);
1008f4dffd8a45386b5a5f0e6de4f30facc9eaac4001The Android Open Source Project            if (DEBUG) Log.d(TAG, "TTFF: " + mTTFF);
1009fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson
1010fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            // notify status listeners
1011fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            synchronized(mListeners) {
1012fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                int size = mListeners.size();
1013fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                for (int i = 0; i < size; i++) {
1014fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    Listener listener = mListeners.get(i);
1015fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    try {
1016f4dffd8a45386b5a5f0e6de4f30facc9eaac4001The Android Open Source Project                        listener.mListener.onFirstFix(mTTFF);
1017fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    } catch (RemoteException e) {
1018fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        Log.w(TAG, "RemoteException in stopNavigating");
1019fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        mListeners.remove(listener);
1020fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        // adjust for size of list changing
1021fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                        size--;
1022fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                    }
1023fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson                }
1024fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson            }
1025fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson        }
1026fa94ff074d3200fae2f5d14a6d0f454e2ad23cfaHakan Gustavsson
102703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        if (mSingleShot) {
102803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            stopNavigating();
102903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
103015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mStarted && mStatus != LocationProvider.AVAILABLE) {
1031d53ba017ee2381383b4bb4d92e6e0e661431660fMike Lockwood            // we want to time out if we do not receive a fix
1032b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood            // within the time out and we are requesting infrequent fixes
103304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {
1034b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood                mAlarmManager.cancel(mTimeoutIntent);
1035b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood            }
1036b7be5447a002b4a1cf7d4030cc8a0a330cd7517cMike Lockwood
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is receiving fixes.
103800b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
103900b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
104115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.AVAILABLE, mSvCount);
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
104329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
104403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood       if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted && mFixInterval > 1000) {
1045d53ba017ee2381383b4bb4d92e6e0e661431660fMike Lockwood            if (DEBUG) Log.d(TAG, "got fix, hibernating");
10460632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            hibernate();
104729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        }
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   }
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our status
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportStatus(int status) {
105429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) Log.v(TAG, "reportStatus status: " + status);
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10562e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
10572e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            boolean wasNavigating = mNavigating;
1058dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood
1059cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            switch (status) {
1060cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_SESSION_BEGIN:
1061cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mNavigating = true;
1062271f9f172b241607b1ed39a7709c3ed47ee5dee7Mike Lockwood                    mEngineOn = true;
1063cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1064cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_SESSION_END:
1065cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mNavigating = false;
1066cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1067cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_ENGINE_ON:
1068cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mEngineOn = true;
1069cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1070cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_ENGINE_OFF:
1071cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mEngineOn = false;
1072271f9f172b241607b1ed39a7709c3ed47ee5dee7Mike Lockwood                    mNavigating = false;
1073cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
1074cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            }
1075cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood
1076dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood            if (wasNavigating != mNavigating) {
1077dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                int size = mListeners.size();
1078dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                for (int i = 0; i < size; i++) {
1079dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    Listener listener = mListeners.get(i);
1080dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    try {
1081dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        if (mNavigating) {
1082dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            listener.mListener.onGpsStarted();
1083dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        } else {
1084dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            listener.mListener.onGpsStopped();
1085dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        }
1086dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    } catch (RemoteException e) {
1087dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        Log.w(TAG, "RemoteException in reportStatus");
1088dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        mListeners.remove(listener);
1089dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        // adjust for size of list changing
1090dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        size--;
1091dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    }
1092dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                }
1093dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood
10942e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
1095dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    // update battery stats
1096dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    for (int i=mClientUids.size() - 1; i >= 0; i--) {
1097dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        int uid = mClientUids.keyAt(i);
1098dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        if (mNavigating) {
1099dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            mBatteryStats.noteStartGps(uid);
1100dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        } else {
1101dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            mBatteryStats.noteStopGps(uid);
1102dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        }
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11042e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
11052e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in reportStatus");
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1108dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                // send an intent to notify that the GPS has been enabled or disabled.
110900b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood                Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
111000b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood                intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
1111dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                mContext.sendBroadcast(intent);
11122f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update SV info
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportSvStatus() {
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(mListeners) {
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int size = mListeners.size();
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < size; i++) {
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Listener listener = mListeners.get(i);
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs,
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSvElevations, mSvAzimuths, mSvMasks[EPHEMERIS_MASK],
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK]);
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.w(TAG, "RemoteException in reportSvInfo");
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mListeners.remove(listener);
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // adjust for size of list changing
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    size--;
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
114029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) {
114129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            Log.v(TAG, "SV count: " + svCount +
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) +
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK]));
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < svCount; i++) {
114529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                Log.v(TAG, "sv: " + mSvs[i] +
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " snr: " + (float)mSnrs[i]/10 +
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " elev: " + mSvElevations[i] +
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " azimuth: " + mSvAzimuths[i] +
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " E") +
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " A") +
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U"));
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11550881f4f9339febee85c9ab4cba69970ac5cbde55Kevin.KY Tsai        // return number of sets used in fix instead of total
11560881f4f9339febee85c9ab4cba69970ac5cbde55Kevin.KY Tsai        updateStatus(mStatus, Integer.bitCount(mSvMasks[USED_FOR_FIX_MASK]));
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
115815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
115904598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is no longer receiving fixes.
116100b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
116200b74270c9f136a8727c5f6cda0997a3a905f385Mike Lockwood            intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
116415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
116758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
116858bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    /**
1169e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood     * called from native code to update AGPS status
117058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood     */
1171e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private void reportAGpsStatus(int type, int status) {
117258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        switch (status) {
1173e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_REQUEST_AGPS_DATA_CONN:
11742acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                // Set mAGpsDataConnectionState before calling startUsingNetworkFeature
11752acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                //  to avoid a race condition with handleUpdateNetworkState()
11762acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
11772acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                int result = mConnMgr.startUsingNetworkFeature(
117858bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                        ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
117958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                if (result == Phone.APN_ALREADY_ACTIVE) {
1180b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    if (mAGpsApn != null) {
1181b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        native_agps_data_conn_open(mAGpsApn);
1182b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
1183b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    } else {
1184b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        Log.e(TAG, "mAGpsApn not set when receiving Phone.APN_ALREADY_ACTIVE");
11852acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
1186b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        native_agps_data_conn_failed();
1187b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    }
118858bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else if (result == Phone.APN_REQUEST_STARTED) {
11892acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                    // Nothing to do here
119058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else {
11912acfd34ccbd39258422333c9c66c586297c97683Mike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
1192e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_failed();
119358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
119458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1195e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_RELEASE_AGPS_DATA_CONN:
1196e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
119758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                    mConnMgr.stopUsingNetworkFeature(
119858bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                            ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
1199e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_closed();
1200e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
120158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
120258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1203e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONNECTED:
1204e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                // Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
120558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1206e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_DONE:
1207e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                // Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
120858bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1209e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_FAILED:
1210e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                // Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
121158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
121258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        }
121358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    }
121458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1215b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    /**
1216b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood     * called from native code to report NMEA data received
1217b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood     */
1218f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood    private void reportNmea(long timestamp) {
1219b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood        synchronized(mListeners) {
1220b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            int size = mListeners.size();
1221b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            if (size > 0) {
1222b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                // don't bother creating the String if we have no listeners
1223f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood                int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
1224b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                String nmea = new String(mNmeaBuffer, 0, length);
1225b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood
1226b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                for (int i = 0; i < size; i++) {
1227b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    Listener listener = mListeners.get(i);
1228b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    try {
1229b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        listener.mListener.onNmeaReceived(timestamp, nmea);
1230b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    } catch (RemoteException e) {
1231b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        Log.w(TAG, "RemoteException in reportNmea");
1232b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        mListeners.remove(listener);
1233b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        // adjust for size of list changing
1234b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        size--;
1235b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    }
1236b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                }
1237b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            }
1238b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood        }
1239b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    }
1240b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood
124162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    /**
124204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood     * called from native code to inform us what the GPS engine capabilities are
124304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood     */
124404598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private void setEngineCapabilities(int capabilities) {
124504598b67a58fad93e5060bb77756ba4863013aedMike Lockwood        mEngineCapabilities = capabilities;
124604598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    }
124704598b67a58fad93e5060bb77756ba4863013aedMike Lockwood
124804598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    /**
124962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood     * called from native code to request XTRA data
125062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood     */
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void xtraDownloadRequest() {
1252f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
125398e48691f738680fe59e7383a41458e7337daccdMike Lockwood        sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
125622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    //=============================================================
125722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // NI Client support
125822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie	//=============================================================
125922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
126022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    	// Sends a response for an NI reqeust to HAL.
126122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    	public boolean sendNiResponse(int notificationId, int userResponse)
126222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    	{
126322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	// TODO Add Permission check
126422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
126522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    		StringBuilder extrasBuf = new StringBuilder();
126622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
1267f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato    		if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
126822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    				", response: " + userResponse);
126922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
127022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    		native_send_ni_response(notificationId, userResponse);
127122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
127222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    		return true;
127322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    	}
127422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    };
127522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
127622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    public INetInitiatedListener getNetInitiatedListener() {
127722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        return mNetInitiatedListener;
127822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    }
127922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
128022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // Called by JNI function to report an NI request.
128122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie	@SuppressWarnings("deprecation")
128222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie	public void reportNiNotification(
128322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int notificationId,
128422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int niType,
128522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int notifyFlags,
128622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int timeout,
128722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int defaultResponse,
128822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	String requestorId,
128922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	String text,
129022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int requestorIdEncoding,
129122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int textEncoding,
129222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	String extras  // Encoded extra data
129322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        )
129422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie	{
129522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		Log.i(TAG, "reportNiNotification: entered");
129622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		Log.i(TAG, "notificationId: " + notificationId +
129722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", niType: " + niType +
129822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", notifyFlags: " + notifyFlags +
129922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", timeout: " + timeout +
130022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", defaultResponse: " + defaultResponse);
130122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
130222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		Log.i(TAG, "requestorId: " + requestorId +
130322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", text: " + text +
130422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", requestorIdEncoding: " + requestorIdEncoding +
130522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", textEncoding: " + textEncoding);
130622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
130722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		GpsNiNotification notification = new GpsNiNotification();
130822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
130922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.notificationId = notificationId;
131022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.niType = niType;
131122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
131222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
131322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
131422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.timeout = timeout;
131522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.defaultResponse = defaultResponse;
131622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.requestorId = requestorId;
131722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.text = text;
131822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.requestorIdEncoding = requestorIdEncoding;
131922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.textEncoding = textEncoding;
132022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
132122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		// Process extras, assuming the format is
132222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		// one of more lines of "key = value"
132322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		Bundle bundle = new Bundle();
132422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
132522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		if (extras == null) extras = "";
132622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		Properties extraProp = new Properties();
132722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
132822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		try {
132922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie			extraProp.load(new StringBufferInputStream(extras));
133022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		}
133122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		catch (IOException e)
133222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		{
133322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie			Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
133422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		}
133522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
133622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		for (Entry<Object, Object> ent : extraProp.entrySet())
133722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		{
133822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie			bundle.putString((String) ent.getKey(), (String) ent.getValue());
133922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		}
134022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
134122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.extras = bundle;
134222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
134322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		mNIHandler.handleNiNotification(notification);
134422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie	}
134522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
134698e48691f738680fe59e7383a41458e7337daccdMike Lockwood    private void sendMessage(int message, int arg, Object obj) {
134798e48691f738680fe59e7383a41458e7337daccdMike Lockwood        // hold a wake lock while messages are pending
134898e48691f738680fe59e7383a41458e7337daccdMike Lockwood        synchronized (mWakeLock) {
134998e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mPendingMessageBits |= (1 << message);
135098e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mWakeLock.acquire();
135198e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.removeMessages(message);
135298e48691f738680fe59e7383a41458e7337daccdMike Lockwood            Message m = Message.obtain(mHandler, message);
135398e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.arg1 = arg;
135498e48691f738680fe59e7383a41458e7337daccdMike Lockwood            m.obj = obj;
135598e48691f738680fe59e7383a41458e7337daccdMike Lockwood            mHandler.sendMessage(m);
135698e48691f738680fe59e7383a41458e7337daccdMike Lockwood        }
135798e48691f738680fe59e7383a41458e7337daccdMike Lockwood    }
135898e48691f738680fe59e7383a41458e7337daccdMike Lockwood
135962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    private final class ProviderHandler extends Handler {
136062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        @Override
136162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        public void handleMessage(Message msg)
136262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood        {
136398e48691f738680fe59e7383a41458e7337daccdMike Lockwood            int message = msg.what;
136498e48691f738680fe59e7383a41458e7337daccdMike Lockwood            switch (message) {
136562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case ENABLE:
136662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    if (msg.arg1 == 1) {
136762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                        handleEnable();
136862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    } else {
136962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                        handleDisable();
13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
137162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
137262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case ENABLE_TRACKING:
137362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleEnableLocationTracking(msg.arg1 == 1);
137462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
137503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                case REQUEST_SINGLE_SHOT:
137603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    handleRequestSingleShot();
137703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    break;
137862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case UPDATE_NETWORK_STATE:
137962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleUpdateNetworkState(msg.arg1, (NetworkInfo)msg.obj);
138062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
138162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case INJECT_NTP_TIME:
138262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleInjectNtpTime();
138362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
138462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case DOWNLOAD_XTRA_DATA:
13851a1cd3a878b6389c097e34d114b60cf953edaeaaMike Lockwood                    if (mSupportsXtra) {
138662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                        handleDownloadXtraData();
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
138862a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
138962a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case UPDATE_LOCATION:
139062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleUpdateLocation((Location)msg.obj);
139162a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
139262a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case ADD_LISTENER:
139362a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleAddListener(msg.arg1);
139462a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
139562a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                case REMOVE_LISTENER:
139662a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    handleRemoveListener(msg.arg1);
139762a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood                    break;
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
139998e48691f738680fe59e7383a41458e7337daccdMike Lockwood            // release wake lock if no messages are pending
140098e48691f738680fe59e7383a41458e7337daccdMike Lockwood            synchronized (mWakeLock) {
140198e48691f738680fe59e7383a41458e7337daccdMike Lockwood                mPendingMessageBits &= ~(1 << message);
140298e48691f738680fe59e7383a41458e7337daccdMike Lockwood                if (message == ADD_LISTENER || message == REMOVE_LISTENER) {
140398e48691f738680fe59e7383a41458e7337daccdMike Lockwood                    mPendingListenerMessages--;
140498e48691f738680fe59e7383a41458e7337daccdMike Lockwood                }
140598e48691f738680fe59e7383a41458e7337daccdMike Lockwood                if (mPendingMessageBits == 0 && mPendingListenerMessages == 0) {
140698e48691f738680fe59e7383a41458e7337daccdMike Lockwood                    mWakeLock.release();
140798e48691f738680fe59e7383a41458e7337daccdMike Lockwood                }
140898e48691f738680fe59e7383a41458e7337daccdMike Lockwood            }
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
141062a8fc159ad8d8044f3cde6ee6d46e9cc56b823fMike Lockwood    };
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
141289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood    private final class GpsLocationProviderThread extends Thread {
141389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood
141489096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        public GpsLocationProviderThread() {
141589096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            super("GpsLocationProvider");
141689096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        }
141789096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood
141889096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        public void run() {
141989096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
142089096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            initialize();
142189096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            Looper.prepare();
142289096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            mHandler = new ProviderHandler();
142389096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            // signal when we are initialized and ready to go
142489096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            mInitializedLatch.countDown();
142589096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood            Looper.loop();
142689096317104722219f73a5c3cc424e6e98c90a61Mike Lockwood        }
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for GPS SV statistics
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int MAX_SVS = 32;
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int EPHEMERIS_MASK = 0;
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int ALMANAC_MASK = 1;
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int USED_FOR_FIX_MASK = 2;
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // preallocated arrays, to avoid memory allocation in reportStatus()
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvs[] = new int[MAX_SVS];
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSnrs[] = new float[MAX_SVS];
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvElevations[] = new float[MAX_SVS];
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvAzimuths[] = new float[MAX_SVS];
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvMasks[] = new int[3];
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvCount;
1442b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    // preallocated to avoid memory allocation in reportNmea()
1443b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    private byte[] mNmeaBuffer = new byte[120];
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static { class_init_native(); }
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native void class_init_native();
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native boolean native_is_supported();
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_init();
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_cleanup();
145104598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private native boolean native_set_position_mode(int mode, int recurrence, int min_interval,
145204598b67a58fad93e5060bb77756ba4863013aedMike Lockwood            int preferred_accuracy, int preferred_time);
145304598b67a58fad93e5060bb77756ba4863013aedMike Lockwood    private native boolean native_start();
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_stop();
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_delete_aiding_data(int flags);
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // returns number of SVs
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // mask[0] is ephemeris mask and mask[1] is almanac mask
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native int native_read_sv_status(int[] svs, float[] snrs,
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] elevations, float[] azimuths, int[] masks);
1460f602d362ba4bb3adbf1eb4e38a794fb14274293aMike Lockwood    private native int native_read_nmea(byte[] buffer, int bufferSize);
1461d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood    private native void native_inject_location(double latitude, double longitude, float accuracy);
1462d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood
14633c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    // XTRA Support
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_time(long time, long timeReference, int uncertainty);
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_supports_xtra();
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_xtra_data(byte[] data, int length);
1467105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
14683c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    // DEBUG Support
14693c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    private native String native_get_internal_state();
14703c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger
14713c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger    // AGPS Support
1472e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_open(String apn);
1473e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_closed();
1474e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_failed();
1475a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood    private native void native_set_agps_server(int type, String hostname, int port);
147622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
147722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // Network-initiated (NI) Support
147822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private native void native_send_ni_response(int notificationId, int userResponse);
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1480