GpsLocationProvider.java revision a4903f254b4711c8fc0ac5f7e3d605f4dce34f35
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
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.internal.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;
33d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwoodimport android.location.LocationProviderInterface;
3458bda987665af759c379cd494ff4873ac61acf29Mike Lockwoodimport android.net.ConnectivityManager;
3503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwoodimport android.net.NetworkInfo;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.SntpClient;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
390528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwoodimport android.os.PowerManager;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
412f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport android.os.ServiceManager;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
43bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwoodimport android.provider.Settings;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
452f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport android.util.SparseIntArray;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
472f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport com.android.internal.app.IBatteryStats;
48105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport com.android.internal.telephony.Phone;
4922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport com.android.internal.location.GpsNetInitiatedHandler;
5022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
51105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileInputStream;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
5522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport java.io.StringBufferInputStream;
56105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport java.net.InetAddress;
57105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport java.net.UnknownHostException;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
59f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwoodimport java.util.Date;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Properties;
6122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport java.util.Map.Entry;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A GPS implementation of LocationProvider used by LocationManager.
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
68d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwoodpublic class GpsLocationProvider implements LocationProviderInterface {
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "GpsLocationProvider";
7129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
72f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato    private static final boolean DEBUG = false;
7329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private static final boolean VERBOSE = false;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcast intent action indicating that the GPS has either been
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * enabled or disabled. An intent extra provides this state as a boolean,
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * where {@code true} means enabled.
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #EXTRA_ENABLED
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String GPS_ENABLED_CHANGE_ACTION =
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "android.location.GPS_ENABLED_CHANGE";
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcast intent action indicating that the GPS has either started or
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * stopped receiving GPS fixes. An intent extra provides this state as a
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * boolean, where {@code true} means that the GPS is actively receiving fixes.
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #EXTRA_ENABLED
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String GPS_FIX_CHANGE_ACTION =
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "android.location.GPS_FIX_CHANGE";
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The lookup key for a boolean that indicates whether GPS is enabled or
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * disabled. {@code true} means GPS is enabled. Retrieve it with
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.content.Intent#getBooleanExtra(String,boolean)}.
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String EXTRA_ENABLED = "enabled";
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
106105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    // these need to match GpsPositionMode enum in gps.h
107105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_STANDALONE = 0;
108105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_MS_BASED = 1;
109105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
110105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these need to match GpsStatusValue defines in gps.h
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_NONE = 0;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_SESSION_BEGIN = 1;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_SESSION_END = 2;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_ENGINE_ON = 3;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_ENGINE_OFF = 4;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
118e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // these need to match GpsApgsStatusValue defines in gps.h
119e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    /** AGPS status event values. */
120e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
121e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
122e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONNECTED = 3;
123e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONN_DONE = 4;
124e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
12558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these need to match GpsLocationFlags enum in gps.h
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_INVALID = 0;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_LAT_LONG = 1;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_ALTITUDE = 2;
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_SPEED = 4;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_BEARING = 8;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_ACCURACY = 16;
133e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
134e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood// IMPORTANT - the GPS_DELETE_* symbols here must match constants in gps.h
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_EPHEMERIS = 0x0001;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_ALMANAC = 0x0002;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_POSITION = 0x0004;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_TIME = 0x0008;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_IONO = 0x0010;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_UTC = 0x0020;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_HEALTH = 0x0040;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SVDIR = 0x0080;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SVSTEER = 0x0100;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SADATA = 0x0200;
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_RTI = 0x0400;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_ALL = 0xFFFF;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
149e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // these need to match AGpsType enum in gps.h
150e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_TYPE_SUPL = 1;
151e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_TYPE_C2K = 2;
152e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
153e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // for mAGpsDataConnectionState
154e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
155e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_OPENING = 1;
156e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_OPEN = 2;
15758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String PROPERTIES_FILE = "/etc/gps.conf";
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mLocationFlags = LOCATION_INVALID;
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current status
16315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time for last status update
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mStatusUpdateTime = SystemClock.elapsedRealtime();
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // turn off GPS fix icon if we haven't received a fix in 10 seconds
1690632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private static final long RECENT_FIX_TIMEOUT = 10;
17029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
17129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    // number of fixes to receive before disabling GPS
17229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private static final int MIN_FIX_COUNT = 10;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1740632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    // stop trying if we do not receive a fix within 60 seconds
1750632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private static final int NO_FIX_TIMEOUT = 60;
1760632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we are enabled
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mEnabled;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we have network connectivity
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNetworkAvailable;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
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
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // requested frequency of fixes, in seconds
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mFixInterval = 1;
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    // number of fixes we have received since we started navigating
19329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private int mFixCount;
19429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we started navigation
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mStarted;
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for calculating time to first fix
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mFixRequestTime = 0;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time to first fix for most recent session
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mTTFF = 0;
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time we received our last fix
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mLastFixTime;
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // properties loaded from PROPERTIES_FILE
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Properties mProperties;
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String mNtpServer;
208734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private String mSuplServerHost;
209734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private int mSuplServerPort;
210734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private String mC2KServerHost;
211734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private int mC2KServerPort;
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final Context mContext;
21415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final ILocationManager mLocationManager;
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Bundle mLocationExtras = new Bundle();
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<Listener> mListeners = new ArrayList<Listener>();
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private GpsEventThread mEventThread;
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private GpsNetworkThread mNetworkThread;
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Object mNetworkThreadLock = new Object();
221105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
222e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private String mAGpsApn;
223e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private int mAGpsDataConnectionState;
2242f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final ConnectivityManager mConnMgr;
22522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private final GpsNetInitiatedHandler mNIHandler;
2262f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
2270528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    // Wakelocks
2280528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final static String WAKELOCK_KEY = "GpsLocationProvider";
2290528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final PowerManager.WakeLock mWakeLock;
2300528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
23129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    // Alarms
23229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
2330632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
23429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final AlarmManager mAlarmManager;
23529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final PendingIntent mWakeupIntent;
2360632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final PendingIntent mTimeoutIntent;
23729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
2382f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final IBatteryStats mBatteryStats;
2392f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final SparseIntArray mClientUids = new SparseIntArray();
240105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // how often to request NTP time, in milliseconds
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current setting 4 hours
243f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood    private static final long NTP_INTERVAL = 4*60*60*1000;
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // how long to wait if we have a network error in NTP or XTRA downloading
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current setting - 5 minutes
246f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood    private static final long RETRY_INTERVAL = 5*60*1000;
247f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood
248f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood    // to avoid injecting bad NTP time, we reject any time fixes that differ from system time
249f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood    // by more than 5 minutes.
250f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood    private static final long MAX_NTP_SYSTEM_TIME_OFFSET = 5*60*1000;
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
25315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
25415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
25515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
25615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
25715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
25815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            synchronized(mListeners) {
25915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
26015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
26115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size; i++) {
26215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
26315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
26415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        // listener already added
26515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        return;
26615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
26715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
26815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
26915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = new Listener(listener);
27015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                binder.linkToDeath(l, 0);
27115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                mListeners.add(l);
27215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
27315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
27415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
27515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void removeGpsStatusListener(IGpsStatusListener listener) {
27615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
27715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
27815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
27915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
28015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            synchronized(mListeners) {
28115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
28215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = null;
28315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
28415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size && l == null; i++) {
28515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
28615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
28715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        l = test;
28815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
28915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
29015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
29115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                if (l != null) {
29215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    mListeners.remove(l);
29315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    binder.unlinkToDeath(l, 0);
29415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
29515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
29615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
29715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    };
29815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
29915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    public IGpsStatusProvider getGpsStatusProvider() {
30015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        return mGpsStatusProvider;
30115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
30215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
30329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
304105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        @Override public void onReceive(Context context, Intent intent) {
305105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            String action = intent.getAction();
306105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
30729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (action.equals(ALARM_WAKEUP)) {
30829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_WAKEUP");
30929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                startNavigating();
3100632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            } else if (action.equals(ALARM_TIMEOUT)) {
3110632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");
3120632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                hibernate();
313105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
314105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
31529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    };
316105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean isSupported() {
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_is_supported();
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3214e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    public GpsLocationProvider(Context context, ILocationManager locationManager) {
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
32315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mLocationManager = locationManager;
32422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        mNIHandler= new GpsNetInitiatedHandler(context, this);
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3260528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // Create a wake lock
3270528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
3280528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
3290528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
33029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
33129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
3320632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
33329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
334105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        IntentFilter intentFilter = new IntentFilter();
33529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        intentFilter.addAction(ALARM_WAKEUP);
3360632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        intentFilter.addAction(ALARM_TIMEOUT);
33729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        context.registerReceiver(mBroadcastReciever, intentFilter);
338105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
33958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
34058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
3412f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        // Battery statistics service to be notified when GPS turns on or off
3422f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
3432f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProperties = new Properties();
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            File file = new File(PROPERTIES_FILE);
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            FileInputStream stream = new FileInputStream(file);
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProperties.load(stream);
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stream.close();
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNtpServer = mProperties.getProperty("NTP_SERVER", null);
351e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
352734d6031a662a275ec68627bd1258159041d44deMike Lockwood            mSuplServerHost = mProperties.getProperty("SUPL_HOST");
353e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            String portString = mProperties.getProperty("SUPL_PORT");
354734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mSuplServerHost != null && portString != null) {
355105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                try {
356734d6031a662a275ec68627bd1258159041d44deMike Lockwood                    mSuplServerPort = Integer.parseInt(portString);
357105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                } catch (NumberFormatException e) {
358e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
359e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                }
360e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            }
361e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
362734d6031a662a275ec68627bd1258159041d44deMike Lockwood            mC2KServerHost = mProperties.getProperty("C2K_HOST");
363e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            portString = mProperties.getProperty("C2K_PORT");
364734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mC2KServerHost != null && portString != null) {
365e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                try {
366734d6031a662a275ec68627bd1258159041d44deMike Lockwood                    mC2KServerPort = Integer.parseInt(portString);
367e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                } catch (NumberFormatException e) {
368e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse C2K_PORT: " + portString);
369105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                }
370105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
377d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood     * Returns the name of this provider.
378d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood     */
379d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    public String getName() {
380d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        return LocationManager.GPS_PROVIDER;
381d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    }
382d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood
383d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    /**
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to a
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * data network (e.g., the Internet), false otherwise.
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresNetwork() {
388a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood        return true;
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
39103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood    public void updateNetworkState(int state, NetworkInfo info) {
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNetworkAvailable = (state == LocationProvider.AVAILABLE);
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
394f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) {
39503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            Log.d(TAG, "updateNetworkState " + (mNetworkAvailable ? "available" : "unavailable")
39603d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                + " info: " + info);
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
39803d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood
39903d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood        if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL
40003d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
40103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            String apnName = info.getExtraInfo();
40203d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            if (mNetworkAvailable && apnName != null && apnName.length() > 0) {
40303d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsApn = apnName;
40403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                if (DEBUG) Log.d(TAG, "call native_agps_data_conn_open");
40503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                native_agps_data_conn_open(apnName);
40603d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
40703d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            } else {
40803d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                if (DEBUG) Log.d(TAG, "call native_agps_data_conn_failed");
40903d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsApn = null;
41003d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
41103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                native_agps_data_conn_failed();
41203d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            }
41303d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood        }
41403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNetworkAvailable && mNetworkThread != null && mEnabled) {
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // signal the network thread when the network becomes available
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNetworkThread.signal();
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
422fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     * This is called to inform us when another location provider returns a location.
423fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     * Someday we might use this for network location injection to aid the GPS
424fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     */
425fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    public void updateLocation(Location location) {
426d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        if (location.hasAccuracy()) {
427d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood            native_inject_location(location.getLatitude(), location.getLongitude(),
428d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood                    location.getAccuracy());
429d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        }
430fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    }
431fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood
432fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    /**
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to a
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * satellite-based positioning system (e.g., GPS), false
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise.
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresSatellite() {
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to an appropriate
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * cellular network (e.g., to make use of cell tower IDs), false
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise.
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresCell() {
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the use of this provider may result in a
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * monetary charge to the user, false if use is free.  It is up to
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * each provider to give accurate information.
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasMonetaryCost() {
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide altitude
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports altitude
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsAltitude() {
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide speed
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports speed
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsSpeed() {
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide bearing
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports bearing
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsBearing() {
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the power requirement for this provider.
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the power requirement for this provider, as one of the
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * constants Criteria.POWER_REQUIREMENT_*.
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getPowerRequirement() {
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Criteria.POWER_HIGH;
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the horizontal accuracy of this provider
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the accuracy of location from this provider, as one
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of the constants Criteria.ACCURACY_*.
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getAccuracy() {
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Criteria.ACCURACY_FINE;
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Enables this provider.  When enabled, calls to getStatus()
5114e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * must be handled.  Hardware may be started up
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the provider is enabled.
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized void enable() {
515f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) Log.d(TAG, "enable");
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabled) return;
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnabled = native_init();
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabled) {
520734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mSuplServerHost != null) {
521734d6031a662a275ec68627bd1258159041d44deMike Lockwood                native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
522734d6031a662a275ec68627bd1258159041d44deMike Lockwood            }
523734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mC2KServerHost != null) {
524734d6031a662a275ec68627bd1258159041d44deMike Lockwood                native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
525734d6031a662a275ec68627bd1258159041d44deMike Lockwood            }
526734d6031a662a275ec68627bd1258159041d44deMike Lockwood
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // run event listener thread while we are enabled
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEventThread = new GpsEventThread();
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEventThread.start();
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (requiresNetwork()) {
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // run network thread for NTP and XTRA support
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mNetworkThread == null) {
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mNetworkThread = new GpsNetworkThread();
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mNetworkThread.start();
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mNetworkThread.signal();
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Failed to enable location provider");
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Disables this provider.  When disabled, calls to getStatus()
5474e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * need not be handled.  Hardware may be shut
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * down while the provider is disabled.
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized void disable() {
551f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) Log.d(TAG, "disable");
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mEnabled) return;
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnabled = false;
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        stopNavigating();
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        native_disable();
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // make sure our event thread exits
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEventThread != null) {
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEventThread.join();
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (InterruptedException e) {
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.w(TAG, "InterruptedException when joining mEventThread");
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEventThread = null;
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNetworkThread != null) {
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNetworkThread.setDone();
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNetworkThread = null;
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
573cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood        // do this before releasing wakelock
574cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood        native_cleanup();
575cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood
576d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood        // The GpsEventThread does not wait for the GPS to shutdown
577d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood        // so we need to report the GPS_STATUS_ENGINE_OFF event here
578d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood        if (mNavigating) {
579cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            reportStatus(GPS_STATUS_SESSION_END);
580cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood        }
581cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood        if (mEngineOn) {
582d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood            reportStatus(GPS_STATUS_ENGINE_OFF);
583d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood        }
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
586d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    public boolean isEnabled() {
587d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        return mEnabled;
588d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    }
589d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getStatus(Bundle extras) {
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras != null) {
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            extras.putInt("satellites", mSvCount);
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatus;
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateStatus(int status, int svCount) {
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (status != mStatus || svCount != mSvCount) {
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatus = status;
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSvCount = svCount;
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationExtras.putInt("satellites", svCount);
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatusUpdateTime = SystemClock.elapsedRealtime();
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public long getStatusUpdateTime() {
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatusUpdateTime;
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void enableLocationTracking(boolean enable) {
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (enable) {
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = 0;
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            startNavigating();
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
61629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            mAlarmManager.cancel(mWakeupIntent);
6170632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            mAlarmManager.cancel(mTimeoutIntent);
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stopNavigating();
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setMinTime(long minTime) {
623f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) Log.d(TAG, "setMinTime " + minTime);
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (minTime >= 0) {
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int interval = (int)(minTime/1000);
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (interval < 1) {
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                interval = 1;
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFixInterval = interval;
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final class Listener implements IBinder.DeathRecipient {
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IGpsStatusListener mListener;
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int mSensors = 0;
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Listener(IGpsStatusListener listener) {
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = listener;
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
644f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato            if (DEBUG) Log.d(TAG, "GPS status listener died");
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(mListeners) {
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mListeners.remove(this);
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
649fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu            if (mListener != null) {
650fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu                mListener.asBinder().unlinkToDeath(this, 0);
651fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu            }
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6552f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    public void addListener(int uid) {
6562e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
6572e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mClientUids.indexOfKey(uid) >= 0) {
6582e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                // Shouldn't be here -- already have this uid.
6592e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                Log.w(TAG, "Duplicate add listener for uid " + uid);
6602e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                return;
6612e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            }
6622e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            mClientUids.put(uid, 0);
6632e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mNavigating) {
6642e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
6652e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    mBatteryStats.noteStartGps(uid);
6662e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
6672e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in addListener");
6682e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                }
6692f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
6702f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
6712f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
6722f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
6732f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    public void removeListener(int uid) {
6742e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
6752e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mClientUids.indexOfKey(uid) < 0) {
6762e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                // Shouldn't be here -- don't have this uid.
6772e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                Log.w(TAG, "Unneeded remove listener for uid " + uid);
6782e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                return;
6792e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            }
6802e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            mClientUids.delete(uid);
6812e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mNavigating) {
6822e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
6832e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    mBatteryStats.noteStopGps(uid);
6842e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
6852e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in removeListener");
6862e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                }
6872f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
6882f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
6892f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
6902f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendExtraCommand(String command, Bundle extras) {
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ("delete_aiding_data".equals(command)) {
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return deleteAidingData(extras);
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
69693bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        if ("force_time_injection".equals(command)) {
69793bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            return forceTimeInjection();
69893bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
69993bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        if ("force_xtra_injection".equals(command)) {
70093bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            if (native_supports_xtra() && mNetworkThread != null) {
70193bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                xtraDownloadRequest();
70293bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                return true;
70393bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            }
70493bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            return false;
70593bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Log.w(TAG, "sendExtraCommand: unknown command " + command);
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean deleteAidingData(Bundle extras) {
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags;
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras == null) {
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = GPS_DELETE_ALL;
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = 0;
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (flags != 0) {
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_delete_aiding_data(flags);
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
74193bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood    private boolean forceTimeInjection() {
742f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) Log.d(TAG, "forceTimeInjection");
74393bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        if (mNetworkThread != null) {
74493bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            mNetworkThread.timeInjectRequest();
74593bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            return true;
74693bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
74793bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        return false;
74893bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood    }
74993bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void startNavigating() {
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStarted) {
75229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (DEBUG) Log.d(TAG, "startNavigating");
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = true;
754bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood            int positionMode;
7552bb99d1e2f0296dd8b09a451575f70f49da30a1bMike Lockwood            if (Settings.Secure.getInt(mContext.getContentResolver(),
756660bbfcc54d48d5d32e64da683c76b9c372c19b1Mike Lockwood                    Settings.Secure.ASSISTED_GPS_ENABLED, 1) != 0) {
757bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood                positionMode = GPS_POSITION_MODE_MS_BASED;
758bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood            } else {
759bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood                positionMode = GPS_POSITION_MODE_STANDALONE;
760bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood            }
761bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood
762bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood            if (!native_start(positionMode, false, mFixInterval)) {
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStarted = false;
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.e(TAG, "native_start failed in startNavigating()");
7650632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                return;
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
76915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
77029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            mFixCount = 0;
77129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            mFixRequestTime = System.currentTimeMillis();
7720632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
7730632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            // and our fix interval is not short
7740632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            if (mFixInterval >= NO_FIX_TIMEOUT) {
7750632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
7760632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                        SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT * 1000, mTimeoutIntent);
7770632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            }
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void stopNavigating() {
78229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (DEBUG) Log.d(TAG, "stopNavigating");
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mStarted) {
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = false;
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_stop();
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = 0;
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = LOCATION_INVALID;
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
79115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7950632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private void hibernate() {
7960632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        // stop GPS until our next fix interval arrives
7970632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        stopNavigating();
7980632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mFixCount = 0;
7990632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mTimeoutIntent);
8000632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mWakeupIntent);
8010632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        long now = SystemClock.elapsedRealtime();
8020632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
8030632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                SystemClock.elapsedRealtime() + mFixInterval * 1000, mWakeupIntent);
8040632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    }
8050632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our position.
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportLocation(int flags, double latitude, double longitude, double altitude,
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float speed, float bearing, float accuracy, long timestamp) {
81129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                " timestamp: " + timestamp);
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mLastFixTime = System.currentTimeMillis();
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // report time to first fix
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mTTFF == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = (int)(mLastFixTime - mFixRequestTime);
818f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato            if (DEBUG) Log.d(TAG, "TTFF: " + mTTFF);
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // notify status listeners
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(mListeners) {
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int size = mListeners.size();
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int i = 0; i < size; i++) {
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Listener listener = mListeners.get(i);
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        listener.mListener.onFirstFix(mTTFF);
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Log.w(TAG, "RemoteException in stopNavigating");
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mListeners.remove(listener);
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // adjust for size of list changing
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        size--;
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mLocation) {
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = flags;
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLatitude(latitude);
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLongitude(longitude);
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setTime(timestamp);
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAltitude(altitude);
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAltitude();
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setSpeed(speed);
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeSpeed();
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setBearing(bearing);
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeBearing();
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAccuracy(accuracy);
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAccuracy();
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
86515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            try {
866a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                mLocationManager.reportLocation(mLocation, false);
86715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            } catch (RemoteException e) {
86815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Log.e(TAG, "RemoteException calling reportLocation");
86915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
87215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mStarted && mStatus != LocationProvider.AVAILABLE) {
8730632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            mAlarmManager.cancel(mTimeoutIntent);
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is receiving fixes.
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent intent = new Intent(GPS_FIX_CHANGE_ACTION);
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(EXTRA_ENABLED, true);
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
87815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.AVAILABLE, mSvCount);
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
88029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
88129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (mFixCount++ >= MIN_FIX_COUNT && mFixInterval > 1) {
88229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (DEBUG) Log.d(TAG, "exceeded MIN_FIX_COUNT");
8830632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            hibernate();
88429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        }
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   }
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our status
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportStatus(int status) {
89129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) Log.v(TAG, "reportStatus status: " + status);
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8932e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
8942e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            boolean wasNavigating = mNavigating;
895dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood
896cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            switch (status) {
897cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_SESSION_BEGIN:
898cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mNavigating = true;
899271f9f172b241607b1ed39a7709c3ed47ee5dee7Mike Lockwood                    mEngineOn = true;
900cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
901cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_SESSION_END:
902cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mNavigating = false;
903cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
904cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_ENGINE_ON:
905cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mEngineOn = true;
906cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
907cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                case GPS_STATUS_ENGINE_OFF:
908cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    mEngineOn = false;
909271f9f172b241607b1ed39a7709c3ed47ee5dee7Mike Lockwood                    mNavigating = false;
910cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood                    break;
911cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            }
912cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood
913cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            // beware, the events can come out of order
914cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            if ((mNavigating || mEngineOn) && !mWakeLock.isHeld()) {
9150528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                if (DEBUG) Log.d(TAG, "Acquiring wakelock");
9160528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                 mWakeLock.acquire();
9170528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
918dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood
919dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood            if (wasNavigating != mNavigating) {
920dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                int size = mListeners.size();
921dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                for (int i = 0; i < size; i++) {
922dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    Listener listener = mListeners.get(i);
923dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    try {
924dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        if (mNavigating) {
925dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            listener.mListener.onGpsStarted();
926dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        } else {
927dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            listener.mListener.onGpsStopped();
928dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        }
929dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    } catch (RemoteException e) {
930dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        Log.w(TAG, "RemoteException in reportStatus");
931dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        mListeners.remove(listener);
932dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        // adjust for size of list changing
933dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        size--;
934dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    }
935dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                }
936dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood
9372e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
938dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    // update battery stats
939dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    for (int i=mClientUids.size() - 1; i >= 0; i--) {
940dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        int uid = mClientUids.keyAt(i);
941dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        if (mNavigating) {
942dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            mBatteryStats.noteStartGps(uid);
943dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        } else {
944dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            mBatteryStats.noteStopGps(uid);
945dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        }
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9472e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
9482e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in reportStatus");
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
951dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                // send an intent to notify that the GPS has been enabled or disabled.
952dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                Intent intent = new Intent(GPS_ENABLED_CHANGE_ACTION);
953dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                intent.putExtra(EXTRA_ENABLED, mNavigating);
954dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                mContext.sendBroadcast(intent);
9552f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
9562f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
957cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            // beware, the events can come out of order
958cf1d8cb36fade2bfbfb94af371de23684e0f7ac7Mike Lockwood            if (!mNavigating && !mEngineOn && mWakeLock.isHeld()) {
9590528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                if (DEBUG) Log.d(TAG, "Releasing wakelock");
9600528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                mWakeLock.release();
9610528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update SV info
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportSvStatus() {
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(mListeners) {
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int size = mListeners.size();
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < size; i++) {
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Listener listener = mListeners.get(i);
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs,
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSvElevations, mSvAzimuths, mSvMasks[EPHEMERIS_MASK],
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK]);
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.w(TAG, "RemoteException in reportSvInfo");
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mListeners.remove(listener);
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // adjust for size of list changing
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    size--;
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
98929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) {
99029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            Log.v(TAG, "SV count: " + svCount +
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) +
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK]));
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < svCount; i++) {
99429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                Log.v(TAG, "sv: " + mSvs[i] +
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " snr: " + (float)mSnrs[i]/10 +
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " elev: " + mSvElevations[i] +
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " azimuth: " + mSvAzimuths[i] +
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " E") +
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " A") +
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U"));
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateStatus(mStatus, svCount);
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
100615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
10070632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT * 1000) {
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is no longer receiving fixes.
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent intent = new Intent(GPS_FIX_CHANGE_ACTION);
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(EXTRA_ENABLED, false);
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
101215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
101558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
101658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    /**
1017e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood     * called from native code to update AGPS status
101858bda987665af759c379cd494ff4873ac61acf29Mike Lockwood     */
1019e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private void reportAGpsStatus(int type, int status) {
102058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        switch (status) {
1021e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_REQUEST_AGPS_DATA_CONN:
102258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                 int result = mConnMgr.startUsingNetworkFeature(
102358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                        ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
102458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                if (result == Phone.APN_ALREADY_ACTIVE) {
1025b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    if (mAGpsApn != null) {
1026b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        native_agps_data_conn_open(mAGpsApn);
1027b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
1028b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    } else {
1029b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        Log.e(TAG, "mAGpsApn not set when receiving Phone.APN_ALREADY_ACTIVE");
1030b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        native_agps_data_conn_failed();
1031b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    }
103258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else if (result == Phone.APN_REQUEST_STARTED) {
1033e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
103458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else {
1035e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_failed();
103658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
103758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1038e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_RELEASE_AGPS_DATA_CONN:
1039e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
104058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                    mConnMgr.stopUsingNetworkFeature(
104158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                            ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
1042e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_closed();
1043e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
104458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
104558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1046e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONNECTED:
1047e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                // Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
104858bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1049e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_DONE:
1050e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                // Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
105158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1052e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_FAILED:
1053e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                // Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
105458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
105558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        }
105658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    }
105758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1058b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    /**
1059b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood     * called from native code to report NMEA data received
1060b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood     */
1061b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    private void reportNmea(int index, long timestamp) {
1062b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood        synchronized(mListeners) {
1063b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            int size = mListeners.size();
1064b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            if (size > 0) {
1065b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                // don't bother creating the String if we have no listeners
1066b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                int length = native_read_nmea(index, mNmeaBuffer, mNmeaBuffer.length);
1067b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                String nmea = new String(mNmeaBuffer, 0, length);
1068b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood
1069b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                for (int i = 0; i < size; i++) {
1070b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    Listener listener = mListeners.get(i);
1071b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    try {
1072b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        listener.mListener.onNmeaReceived(timestamp, nmea);
1073b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    } catch (RemoteException e) {
1074b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        Log.w(TAG, "RemoteException in reportNmea");
1075b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        mListeners.remove(listener);
1076b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        // adjust for size of list changing
1077b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        size--;
1078b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    }
1079b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                }
1080b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            }
1081b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood        }
1082b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    }
1083b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void xtraDownloadRequest() {
1085f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato        if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNetworkThread != null) {
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNetworkThread.xtraDownloadRequest();
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
109122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    //=============================================================
109222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // NI Client support
109322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie	//=============================================================
109422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
109522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    	// Sends a response for an NI reqeust to HAL.
109622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    	public boolean sendNiResponse(int notificationId, int userResponse)
109722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    	{
109822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	// TODO Add Permission check
109922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
110022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    		StringBuilder extrasBuf = new StringBuilder();
110122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
1102f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato    		if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
110322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    				", response: " + userResponse);
110422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
110522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    		native_send_ni_response(notificationId, userResponse);
110622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
110722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    		return true;
110822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    	}
110922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    };
111022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
111122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    public INetInitiatedListener getNetInitiatedListener() {
111222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        return mNetInitiatedListener;
111322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    }
111422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
111522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // Called by JNI function to report an NI request.
111622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie	@SuppressWarnings("deprecation")
111722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie	public void reportNiNotification(
111822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int notificationId,
111922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int niType,
112022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int notifyFlags,
112122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int timeout,
112222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int defaultResponse,
112322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	String requestorId,
112422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	String text,
112522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int requestorIdEncoding,
112622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int textEncoding,
112722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	String extras  // Encoded extra data
112822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        )
112922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie	{
113022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		Log.i(TAG, "reportNiNotification: entered");
113122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		Log.i(TAG, "notificationId: " + notificationId +
113222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", niType: " + niType +
113322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", notifyFlags: " + notifyFlags +
113422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", timeout: " + timeout +
113522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", defaultResponse: " + defaultResponse);
113622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
113722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		Log.i(TAG, "requestorId: " + requestorId +
113822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", text: " + text +
113922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", requestorIdEncoding: " + requestorIdEncoding +
114022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", textEncoding: " + textEncoding);
114122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
114222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		GpsNiNotification notification = new GpsNiNotification();
114322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
114422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.notificationId = notificationId;
114522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.niType = niType;
114622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
114722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
114822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
114922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.timeout = timeout;
115022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.defaultResponse = defaultResponse;
115122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.requestorId = requestorId;
115222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.text = text;
115322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.requestorIdEncoding = requestorIdEncoding;
115422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.textEncoding = textEncoding;
115522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
115622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		// Process extras, assuming the format is
115722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		// one of more lines of "key = value"
115822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		Bundle bundle = new Bundle();
115922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
116022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		if (extras == null) extras = "";
116122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		Properties extraProp = new Properties();
116222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
116322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		try {
116422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie			extraProp.load(new StringBufferInputStream(extras));
116522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		}
116622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		catch (IOException e)
116722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		{
116822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie			Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
116922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		}
117022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
117122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		for (Entry<Object, Object> ent : extraProp.entrySet())
117222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		{
117322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie			bundle.putString((String) ent.getKey(), (String) ent.getValue());
117422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		}
117522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
117622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.extras = bundle;
117722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
117822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		mNIHandler.handleNiNotification(notification);
117922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie	}
118022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class GpsEventThread extends Thread {
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public GpsEventThread() {
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super("GpsEventThread");
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
1188f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato            if (DEBUG) Log.d(TAG, "GpsEventThread starting");
1189d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood            // Exit as soon as disable() is called instead of waiting for the GPS to stop.
1190d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood            while (mEnabled) {
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // this will wait for an event from the GPS,
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // which will be reported via reportLocation or reportStatus
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                native_wait_for_event();
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1195f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato            if (DEBUG) Log.d(TAG, "GpsEventThread exiting");
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class GpsNetworkThread extends Thread {
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private long mNextNtpTime = 0;
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private long mNextXtraTime = 0;
120393bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        private boolean mTimeInjectRequested = false;
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mXtraDownloadRequested = false;
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mDone = false;
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public GpsNetworkThread() {
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super("GpsNetworkThread");
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mNetworkThreadLock) {
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!mDone) {
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    runLocked();
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void runLocked() {
1220f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato            if (DEBUG) Log.d(TAG, "NetworkThread starting");
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SntpClient client = new SntpClient();
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            GpsXtraDownloader xtraDownloader = null;
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (native_supports_xtra()) {
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // thread exits after disable() is called
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while (!mDone) {
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long waitTime = getWaitTime();
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                do {
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    synchronized (this) {
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        try {
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (!mNetworkAvailable) {
1236f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato                                if (DEBUG) Log.d(TAG, "NetworkThread wait for network");
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                wait();
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            } else if (waitTime > 0) {
1239f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato                                if (DEBUG) {
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    Log.d(TAG, "NetworkThread wait for " +
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                            waitTime + "ms");
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                wait(waitTime);
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } catch (InterruptedException e) {
1246f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato                            if (DEBUG) {
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                Log.d(TAG, "InterruptedException in GpsNetworkThread");
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    waitTime = getWaitTime();
1252e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                } while (!mDone && ((!mXtraDownloadRequested &&
1253a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood                        !mTimeInjectRequested && waitTime > 0)
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || !mNetworkAvailable));
1255f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato                if (DEBUG) Log.d(TAG, "NetworkThread out of wake loop");
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!mDone) {
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (mNtpServer != null &&
125893bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                            (mTimeInjectRequested || mNextNtpTime <= System.currentTimeMillis())) {
1259f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato                        if (DEBUG) {
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            Log.d(TAG, "Requesting time from NTP server " + mNtpServer);
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
126293bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                        mTimeInjectRequested = false;
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (client.requestTime(mNtpServer, 10000)) {
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            long time = client.getNtpTime();
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            long timeReference = client.getNtpTimeReference();
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            int certainty = (int)(client.getRoundTripTime()/2);
1267f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood                            long now = System.currentTimeMillis();
1268f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood                            long systemTimeOffset = time - now;
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1270f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood                            Log.d(TAG, "NTP server returned: "
1271f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood                                    + time + " (" + new Date(time)
1272f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood                                    + ") reference: " + timeReference
1273f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood                                    + " certainty: " + certainty
1274f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood                                    + " system time offset: " + systemTimeOffset);
1275f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood
1276f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood                            // sanity check NTP time and do not use if it is too far from system time
1277f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood                            if (systemTimeOffset < 0) {
1278f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood                                systemTimeOffset = -systemTimeOffset;
1279f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood                            }
1280f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood                            if (systemTimeOffset < MAX_NTP_SYSTEM_TIME_OFFSET) {
1281f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood                                native_inject_time(time, timeReference, certainty);
1282f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood                            } else {
1283f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood                                Log.e(TAG, "NTP time differs from system time by " + systemTimeOffset
1284f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood                                        + "ms.  Ignoring.");
1285f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood                            }
1286f1218be2d8f68f3f445f3bc90e0eca01946a0ddfMike Lockwood                            mNextNtpTime = now + NTP_INTERVAL;
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
1288f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato                            if (DEBUG) Log.d(TAG, "requestTime failed");
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mNextNtpTime = System.currentTimeMillis() + RETRY_INTERVAL;
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if ((mXtraDownloadRequested ||
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (mNextXtraTime > 0 && mNextXtraTime <= System.currentTimeMillis()))
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            && xtraDownloader != null) {
129693bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                        mXtraDownloadRequested = false;
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        byte[] data = xtraDownloader.downloadXtraData();
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (data != null) {
1299f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato                            if (DEBUG) {
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                Log.d(TAG, "calling native_inject_xtra_data");
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            native_inject_xtra_data(data, data.length);
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mNextXtraTime = 0;
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mNextXtraTime = System.currentTimeMillis() + RETRY_INTERVAL;
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1310f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato            if (DEBUG) Log.d(TAG, "NetworkThread exiting");
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized void xtraDownloadRequest() {
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mXtraDownloadRequested = true;
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notify();
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
131893bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        synchronized void timeInjectRequest() {
131993bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            mTimeInjectRequested = true;
132093bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            notify();
132193bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
132293bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized void signal() {
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notify();
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized void setDone() {
1328f5d95cbc1a6974afeb4d3155bdaa8dae55722a39Joe Onorato            if (DEBUG) Log.d(TAG, "stopping NetworkThread");
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDone = true;
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notify();
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private long getWaitTime() {
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long now = System.currentTimeMillis();
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long waitTime = Long.MAX_VALUE;
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mNtpServer != null) {
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                waitTime = mNextNtpTime - now;
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mNextXtraTime != 0) {
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long xtraWaitTime = mNextXtraTime - now;
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (xtraWaitTime < waitTime) {
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    waitTime = xtraWaitTime;
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (waitTime < 0) {
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                waitTime = 0;
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return waitTime;
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for GPS SV statistics
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int MAX_SVS = 32;
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int EPHEMERIS_MASK = 0;
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int ALMANAC_MASK = 1;
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int USED_FOR_FIX_MASK = 2;
13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // preallocated arrays, to avoid memory allocation in reportStatus()
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvs[] = new int[MAX_SVS];
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSnrs[] = new float[MAX_SVS];
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvElevations[] = new float[MAX_SVS];
13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvAzimuths[] = new float[MAX_SVS];
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvMasks[] = new int[3];
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvCount;
1365b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    // preallocated to avoid memory allocation in reportNmea()
1366b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    private byte[] mNmeaBuffer = new byte[120];
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static { class_init_native(); }
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native void class_init_native();
13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native boolean native_is_supported();
13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_init();
13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_disable();
13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_cleanup();
1375105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private native boolean native_start(int positionMode, boolean singleFix, int fixInterval);
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_stop();
13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_set_fix_frequency(int fixFrequency);
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_delete_aiding_data(int flags);
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_wait_for_event();
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // returns number of SVs
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // mask[0] is ephemeris mask and mask[1] is almanac mask
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native int native_read_sv_status(int[] svs, float[] snrs,
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] elevations, float[] azimuths, int[] masks);
1384b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    private native int native_read_nmea(int index, byte[] buffer, int bufferSize);
1385d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood    private native void native_inject_location(double latitude, double longitude, float accuracy);
1386d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // XTRA Support
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_time(long time, long timeReference, int uncertainty);
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_supports_xtra();
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_xtra_data(byte[] data, int length);
1391105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1392e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // AGPS Support
1393e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_open(String apn);
1394e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_closed();
1395e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_failed();
1396a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood    private native void native_set_agps_server(int type, String hostname, int port);
139722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
139822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // Network-initiated (NI) Support
139922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private native void native_send_ni_response(int notificationId, int userResponse);
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1401