GpsLocationProvider.java revision 660bbfcc54d48d5d32e64da683c76b9c372c19b1
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;
2915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwoodimport android.location.ILocationProvider;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Location;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationManager;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationProvider;
3358bda987665af759c379cd494ff4873ac61acf29Mike Lockwoodimport android.net.ConnectivityManager;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.SntpClient;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
370528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwoodimport android.os.PowerManager;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
392f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport android.os.ServiceManager;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
41bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwoodimport android.provider.Settings;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Config;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
442f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport android.util.SparseIntArray;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
462f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport com.android.internal.app.IBatteryStats;
47105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport com.android.internal.telephony.Phone;
48105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport com.android.internal.telephony.TelephonyIntents;
49105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileInputStream;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
53105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport java.net.InetAddress;
54105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport java.net.UnknownHostException;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Properties;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A GPS implementation of LocationProvider used by LocationManager.
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
6315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwoodpublic class GpsLocationProvider extends ILocationProvider.Stub {
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "GpsLocationProvider";
6629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
6729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private static final boolean DEBUG = true;
6829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private static final boolean VERBOSE = false;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcast intent action indicating that the GPS has either been
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * enabled or disabled. An intent extra provides this state as a boolean,
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * where {@code true} means enabled.
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #EXTRA_ENABLED
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String GPS_ENABLED_CHANGE_ACTION =
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "android.location.GPS_ENABLED_CHANGE";
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcast intent action indicating that the GPS has either started or
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * stopped receiving GPS fixes. An intent extra provides this state as a
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * boolean, where {@code true} means that the GPS is actively receiving fixes.
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #EXTRA_ENABLED
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String GPS_FIX_CHANGE_ACTION =
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "android.location.GPS_FIX_CHANGE";
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The lookup key for a boolean that indicates whether GPS is enabled or
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * disabled. {@code true} means GPS is enabled. Retrieve it with
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.content.Intent#getBooleanExtra(String,boolean)}.
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String EXTRA_ENABLED = "enabled";
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
101105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    // these need to match GpsPositionMode enum in gps.h
102105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_STANDALONE = 0;
103105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_MS_BASED = 1;
104105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
105105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these need to match GpsStatusValue defines in gps.h
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_NONE = 0;
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_SESSION_BEGIN = 1;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_SESSION_END = 2;
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_ENGINE_ON = 3;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_ENGINE_OFF = 4;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
113e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // these need to match GpsApgsStatusValue defines in gps.h
114e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    /** AGPS status event values. */
115e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
116e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
117e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONNECTED = 3;
118e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONN_DONE = 4;
119e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
12058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these need to match GpsLocationFlags enum in gps.h
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_INVALID = 0;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_LAT_LONG = 1;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_ALTITUDE = 2;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_SPEED = 4;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_BEARING = 8;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_ACCURACY = 16;
128e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
129e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood// IMPORTANT - the GPS_DELETE_* symbols here must match constants in gps.h
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_EPHEMERIS = 0x0001;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_ALMANAC = 0x0002;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_POSITION = 0x0004;
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_TIME = 0x0008;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_IONO = 0x0010;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_UTC = 0x0020;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_HEALTH = 0x0040;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SVDIR = 0x0080;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SVSTEER = 0x0100;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SADATA = 0x0200;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_RTI = 0x0400;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_ALL = 0xFFFF;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
144e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // these need to match AGpsType enum in gps.h
145e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_TYPE_SUPL = 1;
146e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_TYPE_C2K = 2;
147e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
148e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // for mAGpsDataConnectionState
149e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
150e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_OPENING = 1;
151e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_OPEN = 2;
15258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String PROPERTIES_FILE = "/etc/gps.conf";
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mLocationFlags = LOCATION_INVALID;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current status
15815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time for last status update
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mStatusUpdateTime = SystemClock.elapsedRealtime();
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // turn off GPS fix icon if we haven't received a fix in 10 seconds
1640632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private static final long RECENT_FIX_TIMEOUT = 10;
16529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
16629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    // number of fixes to receive before disabling GPS
16729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private static final int MIN_FIX_COUNT = 10;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1690632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    // stop trying if we do not receive a fix within 60 seconds
1700632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private static final int NO_FIX_TIMEOUT = 60;
1710632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we are enabled
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mEnabled;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we have network connectivity
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNetworkAvailable;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if GPS is navigating
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNavigating;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // requested frequency of fixes, in seconds
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mFixInterval = 1;
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    // number of fixes we have received since we started navigating
18529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private int mFixCount;
18629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we started navigation
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mStarted;
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for calculating time to first fix
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mFixRequestTime = 0;
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time to first fix for most recent session
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mTTFF = 0;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time we received our last fix
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mLastFixTime;
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // properties loaded from PROPERTIES_FILE
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Properties mProperties;
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String mNtpServer;
200734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private String mSuplServerHost;
201734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private int mSuplServerPort;
202734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private String mC2KServerHost;
203734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private int mC2KServerPort;
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final Context mContext;
20615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final ILocationManager mLocationManager;
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Bundle mLocationExtras = new Bundle();
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<Listener> mListeners = new ArrayList<Listener>();
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private GpsEventThread mEventThread;
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private GpsNetworkThread mNetworkThread;
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Object mNetworkThreadLock = new Object();
213105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
214e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private String mAGpsApn;
215e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private int mAGpsDataConnectionState;
2162f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final ConnectivityManager mConnMgr;
2172f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
2180528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    // Wakelocks
2190528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final static String WAKELOCK_KEY = "GpsLocationProvider";
2200528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final PowerManager.WakeLock mWakeLock;
2210528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
22229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    // Alarms
22329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
2240632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
22529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final AlarmManager mAlarmManager;
22629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final PendingIntent mWakeupIntent;
2270632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final PendingIntent mTimeoutIntent;
22829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
2292f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final IBatteryStats mBatteryStats;
2302f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final SparseIntArray mClientUids = new SparseIntArray();
231105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // how often to request NTP time, in milliseconds
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current setting 4 hours
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final long NTP_INTERVAL = 4*60*60*1000;
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // how long to wait if we have a network error in NTP or XTRA downloading
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current setting - 5 minutes
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final long RETRY_INTERVAL = 5*60*1000;
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
24015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
24115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
24215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
24315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
24415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
24515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            synchronized(mListeners) {
24615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
24715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
24815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size; i++) {
24915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
25015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
25115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        // listener already added
25215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        return;
25315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
25415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
25515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
25615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = new Listener(listener);
25715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                binder.linkToDeath(l, 0);
25815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                mListeners.add(l);
25915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
26015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
26115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
26215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void removeGpsStatusListener(IGpsStatusListener listener) {
26315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
26415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
26515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
26615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
26715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            synchronized(mListeners) {
26815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
26915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = null;
27015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
27115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size && l == null; i++) {
27215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
27315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
27415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        l = test;
27515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
27615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
27715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
27815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                if (l != null) {
27915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    mListeners.remove(l);
28015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    binder.unlinkToDeath(l, 0);
28115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
28215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
28315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
28415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    };
28515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
28615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    public IGpsStatusProvider getGpsStatusProvider() {
28715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        return mGpsStatusProvider;
28815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
28915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
29029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
291105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        @Override public void onReceive(Context context, Intent intent) {
292105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            String action = intent.getAction();
293105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
29429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (action.equals(ALARM_WAKEUP)) {
29529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_WAKEUP");
29629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                startNavigating();
2970632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            } else if (action.equals(ALARM_TIMEOUT)) {
2980632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");
2990632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                hibernate();
30029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            } else if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
301105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                String state = intent.getStringExtra(Phone.STATE_KEY);
302105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                String apnName = intent.getStringExtra(Phone.DATA_APN_KEY);
303105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                String reason = intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY);
304105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
305105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                if (Config.LOGD) {
306105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    Log.d(TAG, "state: " + state +  " apnName: " + apnName + " reason: " + reason);
307105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                }
308e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                // FIXME - might not have an APN on CDMA
309375cbb47ff721a26b62385211b82a7cf26db0395Mike Lockwood                if ("CONNECTED".equals(state) && apnName != null && apnName.length() > 0) {
310e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    mAGpsApn = apnName;
311e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
312e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                        native_agps_data_conn_open(mAGpsApn);
313e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
31458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                    }
315105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                }
316105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
317105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
31829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    };
319105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean isSupported() {
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_is_supported();
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3244e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    public GpsLocationProvider(Context context, ILocationManager locationManager) {
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
32615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mLocationManager = locationManager;
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3280528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // Create a wake lock
3290528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
3300528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
3310528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
33229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
33329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
3340632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
33529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
336105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        IntentFilter intentFilter = new IntentFilter();
33729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        intentFilter.addAction(ALARM_WAKEUP);
3380632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        intentFilter.addAction(ALARM_TIMEOUT);
339105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        intentFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
34029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        context.registerReceiver(mBroadcastReciever, intentFilter);
341105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
34258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
34358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
3442f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        // Battery statistics service to be notified when GPS turns on or off
3452f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
3462f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProperties = new Properties();
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            File file = new File(PROPERTIES_FILE);
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            FileInputStream stream = new FileInputStream(file);
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProperties.load(stream);
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stream.close();
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNtpServer = mProperties.getProperty("NTP_SERVER", null);
354e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
355734d6031a662a275ec68627bd1258159041d44deMike Lockwood            mSuplServerHost = mProperties.getProperty("SUPL_HOST");
356e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            String portString = mProperties.getProperty("SUPL_PORT");
357734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mSuplServerHost != null && portString != null) {
358105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                try {
359734d6031a662a275ec68627bd1258159041d44deMike Lockwood                    mSuplServerPort = Integer.parseInt(portString);
360105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                } catch (NumberFormatException e) {
361e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
362e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                }
363e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            }
364e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
365734d6031a662a275ec68627bd1258159041d44deMike Lockwood            mC2KServerHost = mProperties.getProperty("C2K_HOST");
366e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            portString = mProperties.getProperty("C2K_PORT");
367734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mC2KServerHost != null && portString != null) {
368e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                try {
369734d6031a662a275ec68627bd1258159041d44deMike Lockwood                    mC2KServerPort = Integer.parseInt(portString);
370e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                } catch (NumberFormatException e) {
371e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse C2K_PORT: " + portString);
372105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                }
373105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to a
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * data network (e.g., the Internet), false otherwise.
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresNetwork() {
384a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood        return true;
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void updateNetworkState(int state) {
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNetworkAvailable = (state == LocationProvider.AVAILABLE);
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Config.LOGD) {
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.d(TAG, "updateNetworkState " + (mNetworkAvailable ? "available" : "unavailable"));
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNetworkAvailable && mNetworkThread != null && mEnabled) {
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // signal the network thread when the network becomes available
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNetworkThread.signal();
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
401fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     * This is called to inform us when another location provider returns a location.
402fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     * Someday we might use this for network location injection to aid the GPS
403fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     */
404fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    public void updateLocation(Location location) {
405d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        if (location.hasAccuracy()) {
406d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood            native_inject_location(location.getLatitude(), location.getLongitude(),
407d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood                    location.getAccuracy());
408d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        }
409fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    }
410fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood
411fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    /**
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to a
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * satellite-based positioning system (e.g., GPS), false
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise.
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresSatellite() {
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to an appropriate
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * cellular network (e.g., to make use of cell tower IDs), false
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise.
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresCell() {
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the use of this provider may result in a
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * monetary charge to the user, false if use is free.  It is up to
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * each provider to give accurate information.
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasMonetaryCost() {
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide altitude
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports altitude
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsAltitude() {
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide speed
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports speed
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsSpeed() {
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide bearing
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports bearing
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsBearing() {
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the power requirement for this provider.
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the power requirement for this provider, as one of the
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * constants Criteria.POWER_REQUIREMENT_*.
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getPowerRequirement() {
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Criteria.POWER_HIGH;
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the horizontal accuracy of this provider
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the accuracy of location from this provider, as one
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of the constants Criteria.ACCURACY_*.
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getAccuracy() {
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Criteria.ACCURACY_FINE;
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Enables this provider.  When enabled, calls to getStatus()
4904e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * must be handled.  Hardware may be started up
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the provider is enabled.
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized void enable() {
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Config.LOGD) Log.d(TAG, "enable");
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabled) return;
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnabled = native_init();
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabled) {
499734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mSuplServerHost != null) {
500734d6031a662a275ec68627bd1258159041d44deMike Lockwood                native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
501734d6031a662a275ec68627bd1258159041d44deMike Lockwood            }
502734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mC2KServerHost != null) {
503734d6031a662a275ec68627bd1258159041d44deMike Lockwood                native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
504734d6031a662a275ec68627bd1258159041d44deMike Lockwood            }
505734d6031a662a275ec68627bd1258159041d44deMike Lockwood
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // run event listener thread while we are enabled
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEventThread = new GpsEventThread();
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEventThread.start();
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (requiresNetwork()) {
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // run network thread for NTP and XTRA support
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mNetworkThread == null) {
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mNetworkThread = new GpsNetworkThread();
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mNetworkThread.start();
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mNetworkThread.signal();
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Failed to enable location provider");
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Disables this provider.  When disabled, calls to getStatus()
5264e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * need not be handled.  Hardware may be shut
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * down while the provider is disabled.
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized void disable() {
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Config.LOGD) Log.d(TAG, "disable");
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mEnabled) return;
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnabled = false;
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        stopNavigating();
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        native_disable();
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // make sure our event thread exits
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEventThread != null) {
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEventThread.join();
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (InterruptedException e) {
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.w(TAG, "InterruptedException when joining mEventThread");
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEventThread = null;
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNetworkThread != null) {
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNetworkThread.setDone();
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNetworkThread = null;
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
552d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood        // The GpsEventThread does not wait for the GPS to shutdown
553d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood        // so we need to report the GPS_STATUS_ENGINE_OFF event here
554d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood        if (mNavigating) {
555d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood            reportStatus(GPS_STATUS_ENGINE_OFF);
556d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood        }
557d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        native_cleanup();
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isEnabled() {
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mEnabled;
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getStatus(Bundle extras) {
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras != null) {
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            extras.putInt("satellites", mSvCount);
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatus;
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateStatus(int status, int svCount) {
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (status != mStatus || svCount != mSvCount) {
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatus = status;
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSvCount = svCount;
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationExtras.putInt("satellites", svCount);
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatusUpdateTime = SystemClock.elapsedRealtime();
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public long getStatusUpdateTime() {
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatusUpdateTime;
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void enableLocationTracking(boolean enable) {
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (enable) {
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = 0;
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            startNavigating();
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
59129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            mAlarmManager.cancel(mWakeupIntent);
5920632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            mAlarmManager.cancel(mTimeoutIntent);
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stopNavigating();
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setMinTime(long minTime) {
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Config.LOGD) Log.d(TAG, "setMinTime " + minTime);
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (minTime >= 0) {
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int interval = (int)(minTime/1000);
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (interval < 1) {
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                interval = 1;
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFixInterval = interval;
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final class Listener implements IBinder.DeathRecipient {
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IGpsStatusListener mListener;
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int mSensors = 0;
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Listener(IGpsStatusListener listener) {
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = listener;
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "GPS status listener died");
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(mListeners) {
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mListeners.remove(this);
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
624fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu            if (mListener != null) {
625fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu                mListener.asBinder().unlinkToDeath(this, 0);
626fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu            }
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6302f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    public void addListener(int uid) {
6312e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
6322e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mClientUids.indexOfKey(uid) >= 0) {
6332e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                // Shouldn't be here -- already have this uid.
6342e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                Log.w(TAG, "Duplicate add listener for uid " + uid);
6352e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                return;
6362e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            }
6372e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            mClientUids.put(uid, 0);
6382e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mNavigating) {
6392e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
6402e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    mBatteryStats.noteStartGps(uid);
6412e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
6422e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in addListener");
6432e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                }
6442f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
6452f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
6462f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
6472f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
6482f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    public void removeListener(int uid) {
6492e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
6502e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mClientUids.indexOfKey(uid) < 0) {
6512e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                // Shouldn't be here -- don't have this uid.
6522e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                Log.w(TAG, "Unneeded remove listener for uid " + uid);
6532e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                return;
6542e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            }
6552e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            mClientUids.delete(uid);
6562e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mNavigating) {
6572e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
6582e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    mBatteryStats.noteStopGps(uid);
6592e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
6602e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in removeListener");
6612e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                }
6622f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
6632f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
6642f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
6652f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendExtraCommand(String command, Bundle extras) {
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ("delete_aiding_data".equals(command)) {
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return deleteAidingData(extras);
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
67193bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        if ("force_time_injection".equals(command)) {
67293bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            return forceTimeInjection();
67393bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
67493bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        if ("force_xtra_injection".equals(command)) {
67593bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            if (native_supports_xtra() && mNetworkThread != null) {
67693bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                xtraDownloadRequest();
67793bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                return true;
67893bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            }
67993bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            return false;
68093bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Log.w(TAG, "sendExtraCommand: unknown command " + command);
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean deleteAidingData(Bundle extras) {
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags;
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras == null) {
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = GPS_DELETE_ALL;
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = 0;
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (flags != 0) {
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_delete_aiding_data(flags);
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
71693bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood    private boolean forceTimeInjection() {
71793bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        if (Config.LOGD) Log.d(TAG, "forceTimeInjection");
71893bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        if (mNetworkThread != null) {
71993bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            mNetworkThread.timeInjectRequest();
72093bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            return true;
72193bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
72293bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        return false;
72393bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood    }
72493bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void startNavigating() {
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStarted) {
72729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (DEBUG) Log.d(TAG, "startNavigating");
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = true;
729bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood            int positionMode;
7302bb99d1e2f0296dd8b09a451575f70f49da30a1bMike Lockwood            if (Settings.Secure.getInt(mContext.getContentResolver(),
731660bbfcc54d48d5d32e64da683c76b9c372c19b1Mike Lockwood                    Settings.Secure.ASSISTED_GPS_ENABLED, 1) != 0) {
732bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood                positionMode = GPS_POSITION_MODE_MS_BASED;
733bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood            } else {
734bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood                positionMode = GPS_POSITION_MODE_STANDALONE;
735bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood            }
736bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood
737bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood            if (!native_start(positionMode, false, mFixInterval)) {
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStarted = false;
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.e(TAG, "native_start failed in startNavigating()");
7400632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                return;
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
74415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
74529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            mFixCount = 0;
74629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            mFixRequestTime = System.currentTimeMillis();
7470632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
7480632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            // and our fix interval is not short
7490632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            if (mFixInterval >= NO_FIX_TIMEOUT) {
7500632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
7510632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                        SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT * 1000, mTimeoutIntent);
7520632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            }
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void stopNavigating() {
75729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (DEBUG) Log.d(TAG, "stopNavigating");
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mStarted) {
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = false;
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_stop();
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = 0;
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = LOCATION_INVALID;
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
76615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7700632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private void hibernate() {
7710632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        // stop GPS until our next fix interval arrives
7720632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        stopNavigating();
7730632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mFixCount = 0;
7740632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mTimeoutIntent);
7750632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mWakeupIntent);
7760632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        long now = SystemClock.elapsedRealtime();
7770632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
7780632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                SystemClock.elapsedRealtime() + mFixInterval * 1000, mWakeupIntent);
7790632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    }
7800632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our position.
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportLocation(int flags, double latitude, double longitude, double altitude,
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float speed, float bearing, float accuracy, long timestamp) {
78629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                " timestamp: " + timestamp);
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mLastFixTime = System.currentTimeMillis();
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // report time to first fix
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mTTFF == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = (int)(mLastFixTime - mFixRequestTime);
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "TTFF: " + mTTFF);
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // notify status listeners
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(mListeners) {
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int size = mListeners.size();
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int i = 0; i < size; i++) {
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Listener listener = mListeners.get(i);
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        listener.mListener.onFirstFix(mTTFF);
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Log.w(TAG, "RemoteException in stopNavigating");
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mListeners.remove(listener);
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // adjust for size of list changing
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        size--;
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mLocation) {
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = flags;
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLatitude(latitude);
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLongitude(longitude);
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setTime(timestamp);
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAltitude(altitude);
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAltitude();
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setSpeed(speed);
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeSpeed();
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setBearing(bearing);
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeBearing();
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAccuracy(accuracy);
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAccuracy();
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
84015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            try {
841275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood                mLocationManager.reportLocation(mLocation);
84215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            } catch (RemoteException e) {
84315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Log.e(TAG, "RemoteException calling reportLocation");
84415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
84715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mStarted && mStatus != LocationProvider.AVAILABLE) {
8480632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            mAlarmManager.cancel(mTimeoutIntent);
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is receiving fixes.
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent intent = new Intent(GPS_FIX_CHANGE_ACTION);
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(EXTRA_ENABLED, true);
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
85315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.AVAILABLE, mSvCount);
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
85529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
85629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (mFixCount++ >= MIN_FIX_COUNT && mFixInterval > 1) {
85729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (DEBUG) Log.d(TAG, "exceeded MIN_FIX_COUNT");
8580632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            hibernate();
85929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        }
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   }
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our status
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportStatus(int status) {
86629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) Log.v(TAG, "reportStatus status: " + status);
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8682e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
8692e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            boolean wasNavigating = mNavigating;
8702e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            mNavigating = (status == GPS_STATUS_SESSION_BEGIN);
8712e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn
8722e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (wasNavigating == mNavigating) {
8732e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                return;
8742e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            }
8752e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn
8760528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (mNavigating) {
8770528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                if (DEBUG) Log.d(TAG, "Acquiring wakelock");
8780528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                 mWakeLock.acquire();
8790528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
8802e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn
8812e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            int size = mListeners.size();
8822e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            for (int i = 0; i < size; i++) {
8832e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                Listener listener = mListeners.get(i);
8842e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
8852e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    if (mNavigating) {
8862e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                        listener.mListener.onGpsStarted();
8872e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    } else {
8882e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                        listener.mListener.onGpsStopped();
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8902e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
8912e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in reportStatus");
8922e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    mListeners.remove(listener);
8932e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    // adjust for size of list changing
8942e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    size--;
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8982f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            try {
8992f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                // update battery stats
9002f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                for (int i=mClientUids.size() - 1; i >= 0; i--) {
9012f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    int uid = mClientUids.keyAt(i);
9022f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    if (mNavigating) {
9032f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                        mBatteryStats.noteStartGps(uid);
9042f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    } else {
9052f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                        mBatteryStats.noteStopGps(uid);
9062f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    }
9072f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                }
9082f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            } catch (RemoteException e) {
9092f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                Log.w(TAG, "RemoteException in reportStatus");
9102f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
9112f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS has been enabled or disabled.
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent intent = new Intent(GPS_ENABLED_CHANGE_ACTION);
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(EXTRA_ENABLED, mNavigating);
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
9160528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
9170528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (!mNavigating) {
9180528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                if (DEBUG) Log.d(TAG, "Releasing wakelock");
9190528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                mWakeLock.release();
9200528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update SV info
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportSvStatus() {
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(mListeners) {
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int size = mListeners.size();
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < size; i++) {
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Listener listener = mListeners.get(i);
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs,
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSvElevations, mSvAzimuths, mSvMasks[EPHEMERIS_MASK],
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK]);
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.w(TAG, "RemoteException in reportSvInfo");
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mListeners.remove(listener);
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // adjust for size of list changing
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    size--;
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
94829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) {
94929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            Log.v(TAG, "SV count: " + svCount +
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) +
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK]));
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < svCount; i++) {
95329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                Log.v(TAG, "sv: " + mSvs[i] +
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " snr: " + (float)mSnrs[i]/10 +
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " elev: " + mSvElevations[i] +
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " azimuth: " + mSvAzimuths[i] +
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " E") +
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " A") +
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U"));
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateStatus(mStatus, svCount);
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
96515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
9660632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT * 1000) {
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is no longer receiving fixes.
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent intent = new Intent(GPS_FIX_CHANGE_ACTION);
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(EXTRA_ENABLED, false);
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
97115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
97458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
97558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    /**
976e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood     * called from native code to update AGPS status
97758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood     */
978e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private void reportAGpsStatus(int type, int status) {
97958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        switch (status) {
980e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_REQUEST_AGPS_DATA_CONN:
98158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                 int result = mConnMgr.startUsingNetworkFeature(
98258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                        ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
98358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                if (result == Phone.APN_ALREADY_ACTIVE) {
984b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    if (mAGpsApn != null) {
985b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        native_agps_data_conn_open(mAGpsApn);
986b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
987b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    } else {
988b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        Log.e(TAG, "mAGpsApn not set when receiving Phone.APN_ALREADY_ACTIVE");
989b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        native_agps_data_conn_failed();
990b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    }
99158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else if (result == Phone.APN_REQUEST_STARTED) {
992e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
99358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else {
994e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_failed();
99558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
99658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
997e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_RELEASE_AGPS_DATA_CONN:
998e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
99958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                    mConnMgr.stopUsingNetworkFeature(
100058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                            ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
1001e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_closed();
1002e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
100358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
100458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1005e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONNECTED:
1006e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                // Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
100758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1008e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_DONE:
1009e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                // Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
101058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1011e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_FAILED:
1012e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                // Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
101358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
101458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        }
101558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    }
101658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1017b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    /**
1018b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood     * called from native code to report NMEA data received
1019b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood     */
1020b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    private void reportNmea(int index, long timestamp) {
1021b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood        synchronized(mListeners) {
1022b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            int size = mListeners.size();
1023b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            if (size > 0) {
1024b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                // don't bother creating the String if we have no listeners
1025b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                int length = native_read_nmea(index, mNmeaBuffer, mNmeaBuffer.length);
1026b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                String nmea = new String(mNmeaBuffer, 0, length);
1027b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood
1028b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                for (int i = 0; i < size; i++) {
1029b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    Listener listener = mListeners.get(i);
1030b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    try {
1031b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        listener.mListener.onNmeaReceived(timestamp, nmea);
1032b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    } catch (RemoteException e) {
1033b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        Log.w(TAG, "RemoteException in reportNmea");
1034b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        mListeners.remove(listener);
1035b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        // adjust for size of list changing
1036b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        size--;
1037b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    }
1038b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                }
1039b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            }
1040b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood        }
1041b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    }
1042b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void xtraDownloadRequest() {
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Config.LOGD) Log.d(TAG, "xtraDownloadRequest");
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNetworkThread != null) {
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNetworkThread.xtraDownloadRequest();
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class GpsEventThread extends Thread {
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public GpsEventThread() {
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super("GpsEventThread");
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "GpsEventThread starting");
1058d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood            // Exit as soon as disable() is called instead of waiting for the GPS to stop.
1059d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood            while (mEnabled) {
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // this will wait for an event from the GPS,
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // which will be reported via reportLocation or reportStatus
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                native_wait_for_event();
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "GpsEventThread exiting");
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class GpsNetworkThread extends Thread {
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private long mNextNtpTime = 0;
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private long mNextXtraTime = 0;
107293bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        private boolean mTimeInjectRequested = false;
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mXtraDownloadRequested = false;
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mDone = false;
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public GpsNetworkThread() {
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super("GpsNetworkThread");
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mNetworkThreadLock) {
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!mDone) {
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    runLocked();
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void runLocked() {
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "NetworkThread starting");
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SntpClient client = new SntpClient();
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            GpsXtraDownloader xtraDownloader = null;
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (native_supports_xtra()) {
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // thread exits after disable() is called
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while (!mDone) {
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long waitTime = getWaitTime();
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                do {
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    synchronized (this) {
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        try {
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (!mNetworkAvailable) {
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (Config.LOGD) Log.d(TAG,
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        "NetworkThread wait for network");
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                wait();
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            } else if (waitTime > 0) {
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (Config.LOGD) {
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    Log.d(TAG, "NetworkThread wait for " +
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                            waitTime + "ms");
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                wait(waitTime);
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } catch (InterruptedException e) {
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (Config.LOGD) {
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                Log.d(TAG, "InterruptedException in GpsNetworkThread");
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    waitTime = getWaitTime();
1122e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                } while (!mDone && ((!mXtraDownloadRequested &&
1123a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood                        !mTimeInjectRequested && waitTime > 0)
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || !mNetworkAvailable));
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (Config.LOGD) Log.d(TAG, "NetworkThread out of wake loop");
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!mDone) {
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (mNtpServer != null &&
112993bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                            (mTimeInjectRequested || mNextNtpTime <= System.currentTimeMillis())) {
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (Config.LOGD) {
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            Log.d(TAG, "Requesting time from NTP server " + mNtpServer);
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
113393bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                        mTimeInjectRequested = false;
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (client.requestTime(mNtpServer, 10000)) {
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            long time = client.getNtpTime();
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            long timeReference = client.getNtpTimeReference();
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            int certainty = (int)(client.getRoundTripTime()/2);
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (Config.LOGD) Log.d(TAG, "calling native_inject_time: " +
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    time + " reference: " + timeReference
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    + " certainty: " + certainty);
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            native_inject_time(time, timeReference, certainty);
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mNextNtpTime = System.currentTimeMillis() + NTP_INTERVAL;
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (Config.LOGD) Log.d(TAG, "requestTime failed");
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mNextNtpTime = System.currentTimeMillis() + RETRY_INTERVAL;
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if ((mXtraDownloadRequested ||
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (mNextXtraTime > 0 && mNextXtraTime <= System.currentTimeMillis()))
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            && xtraDownloader != null) {
115493bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                        mXtraDownloadRequested = false;
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        byte[] data = xtraDownloader.downloadXtraData();
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (data != null) {
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (Config.LOGD) {
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                Log.d(TAG, "calling native_inject_xtra_data");
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            native_inject_xtra_data(data, data.length);
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mNextXtraTime = 0;
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mNextXtraTime = System.currentTimeMillis() + RETRY_INTERVAL;
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "NetworkThread exiting");
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized void xtraDownloadRequest() {
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mXtraDownloadRequested = true;
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notify();
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
117693bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        synchronized void timeInjectRequest() {
117793bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            mTimeInjectRequested = true;
117893bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            notify();
117993bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
118093bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized void signal() {
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notify();
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized void setDone() {
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "stopping NetworkThread");
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDone = true;
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notify();
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private long getWaitTime() {
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long now = System.currentTimeMillis();
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long waitTime = Long.MAX_VALUE;
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mNtpServer != null) {
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                waitTime = mNextNtpTime - now;
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mNextXtraTime != 0) {
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long xtraWaitTime = mNextXtraTime - now;
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (xtraWaitTime < waitTime) {
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    waitTime = xtraWaitTime;
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (waitTime < 0) {
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                waitTime = 0;
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return waitTime;
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for GPS SV statistics
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int MAX_SVS = 32;
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int EPHEMERIS_MASK = 0;
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int ALMANAC_MASK = 1;
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int USED_FOR_FIX_MASK = 2;
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // preallocated arrays, to avoid memory allocation in reportStatus()
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvs[] = new int[MAX_SVS];
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSnrs[] = new float[MAX_SVS];
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvElevations[] = new float[MAX_SVS];
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvAzimuths[] = new float[MAX_SVS];
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvMasks[] = new int[3];
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvCount;
1223b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    // preallocated to avoid memory allocation in reportNmea()
1224b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    private byte[] mNmeaBuffer = new byte[120];
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static { class_init_native(); }
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native void class_init_native();
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native boolean native_is_supported();
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_init();
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_disable();
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_cleanup();
1233105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private native boolean native_start(int positionMode, boolean singleFix, int fixInterval);
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_stop();
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_set_fix_frequency(int fixFrequency);
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_delete_aiding_data(int flags);
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_wait_for_event();
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // returns number of SVs
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // mask[0] is ephemeris mask and mask[1] is almanac mask
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native int native_read_sv_status(int[] svs, float[] snrs,
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] elevations, float[] azimuths, int[] masks);
1242b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    private native int native_read_nmea(int index, byte[] buffer, int bufferSize);
1243d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood    private native void native_inject_location(double latitude, double longitude, float accuracy);
1244d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // XTRA Support
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_time(long time, long timeReference, int uncertainty);
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_supports_xtra();
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_xtra_data(byte[] data, int length);
1249105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1250e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // AGPS Support
1251e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_open(String apn);
1252e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_closed();
1253e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_failed();
1254a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood    private native void native_set_agps_server(int type, String hostname, int port);
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1256