GpsLocationProvider.java revision a9e546169b3c2c9c5f248d2f3abe3b934f48695d
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;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Config;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
432f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport android.util.SparseIntArray;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
452f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport com.android.internal.app.IBatteryStats;
46105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport com.android.internal.telephony.Phone;
47105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport com.android.internal.telephony.TelephonyIntents;
48105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileInputStream;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
52105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport java.net.InetAddress;
53105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport java.net.UnknownHostException;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Properties;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A GPS implementation of LocationProvider used by LocationManager.
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
6215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwoodpublic class GpsLocationProvider extends ILocationProvider.Stub {
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "GpsLocationProvider";
6529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
6629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private static final boolean DEBUG = true;
6729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private static final boolean VERBOSE = false;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcast intent action indicating that the GPS has either been
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * enabled or disabled. An intent extra provides this state as a boolean,
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * where {@code true} means enabled.
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #EXTRA_ENABLED
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String GPS_ENABLED_CHANGE_ACTION =
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "android.location.GPS_ENABLED_CHANGE";
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcast intent action indicating that the GPS has either started or
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * stopped receiving GPS fixes. An intent extra provides this state as a
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * boolean, where {@code true} means that the GPS is actively receiving fixes.
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #EXTRA_ENABLED
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String GPS_FIX_CHANGE_ACTION =
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "android.location.GPS_FIX_CHANGE";
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The lookup key for a boolean that indicates whether GPS is enabled or
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * disabled. {@code true} means GPS is enabled. Retrieve it with
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.content.Intent#getBooleanExtra(String,boolean)}.
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String EXTRA_ENABLED = "enabled";
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
100105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    // these need to match GpsPositionMode enum in gps.h
101105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_STANDALONE = 0;
102105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_MS_BASED = 1;
103105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
104105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these need to match GpsStatusValue defines in gps.h
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_NONE = 0;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_SESSION_BEGIN = 1;
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_SESSION_END = 2;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_ENGINE_ON = 3;
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_ENGINE_OFF = 4;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
112e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // these need to match GpsApgsStatusValue defines in gps.h
113e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    /** AGPS status event values. */
114e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
115e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
116e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONNECTED = 3;
117e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONN_DONE = 4;
118e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
11958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these need to match GpsLocationFlags enum in gps.h
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_INVALID = 0;
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_LAT_LONG = 1;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_ALTITUDE = 2;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_SPEED = 4;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_BEARING = 8;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_ACCURACY = 16;
127e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
128e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood// IMPORTANT - the GPS_DELETE_* symbols here must match constants in gps.h
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_EPHEMERIS = 0x0001;
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_ALMANAC = 0x0002;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_POSITION = 0x0004;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_TIME = 0x0008;
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_IONO = 0x0010;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_UTC = 0x0020;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_HEALTH = 0x0040;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SVDIR = 0x0080;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SVSTEER = 0x0100;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SADATA = 0x0200;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_RTI = 0x0400;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_ALL = 0xFFFF;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
143e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // these need to match AGpsType enum in gps.h
144e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_TYPE_SUPL = 1;
145e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_TYPE_C2K = 2;
146e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
147e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // for mAGpsDataConnectionState
148e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
149e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_OPENING = 1;
150e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_OPEN = 2;
15158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String PROPERTIES_FILE = "/etc/gps.conf";
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mLocationFlags = LOCATION_INVALID;
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current status
15715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time for last status update
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mStatusUpdateTime = SystemClock.elapsedRealtime();
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // turn off GPS fix icon if we haven't received a fix in 10 seconds
1630632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private static final long RECENT_FIX_TIMEOUT = 10;
16429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
16529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    // number of fixes to receive before disabling GPS
16629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private static final int MIN_FIX_COUNT = 10;
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1680632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    // stop trying if we do not receive a fix within 60 seconds
1690632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private static final int NO_FIX_TIMEOUT = 60;
1700632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we are enabled
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mEnabled;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we have network connectivity
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNetworkAvailable;
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if GPS is navigating
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNavigating;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // requested frequency of fixes, in seconds
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mFixInterval = 1;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    // number of fixes we have received since we started navigating
18429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private int mFixCount;
18529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
186105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private int mPositionMode = GPS_POSITION_MODE_STANDALONE;
187105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we started navigation
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mStarted;
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for calculating time to first fix
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mFixRequestTime = 0;
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time to first fix for most recent session
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mTTFF = 0;
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time we received our last fix
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mLastFixTime;
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // properties loaded from PROPERTIES_FILE
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Properties mProperties;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String mNtpServer;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final Context mContext;
20315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final ILocationManager mLocationManager;
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Bundle mLocationExtras = new Bundle();
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<Listener> mListeners = new ArrayList<Listener>();
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private GpsEventThread mEventThread;
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private GpsNetworkThread mNetworkThread;
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Object mNetworkThreadLock = new Object();
210105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
211e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private String mAGpsApn;
212e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private int mAGpsDataConnectionState;
2132f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final ConnectivityManager mConnMgr;
2142f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
2150528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    // Wakelocks
2160528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final static String WAKELOCK_KEY = "GpsLocationProvider";
2170528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final PowerManager.WakeLock mWakeLock;
2180528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
21929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    // Alarms
22029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
2210632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
22229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final AlarmManager mAlarmManager;
22329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final PendingIntent mWakeupIntent;
2240632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final PendingIntent mTimeoutIntent;
22529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
2262f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final IBatteryStats mBatteryStats;
2272f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final SparseIntArray mClientUids = new SparseIntArray();
228105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // how often to request NTP time, in milliseconds
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current setting 4 hours
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final long NTP_INTERVAL = 4*60*60*1000;
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // how long to wait if we have a network error in NTP or XTRA downloading
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current setting - 5 minutes
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final long RETRY_INTERVAL = 5*60*1000;
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
23715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
23815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
23915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
24015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
24115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
24215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            synchronized(mListeners) {
24315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
24415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
24515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size; i++) {
24615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
24715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
24815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        // listener already added
24915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        return;
25015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
25115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
25215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
25315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = new Listener(listener);
25415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                binder.linkToDeath(l, 0);
25515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                mListeners.add(l);
25615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
25715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
25815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
25915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void removeGpsStatusListener(IGpsStatusListener listener) {
26015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
26115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
26215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
26315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
26415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            synchronized(mListeners) {
26515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
26615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = null;
26715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
26815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size && l == null; i++) {
26915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
27015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
27115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        l = test;
27215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
27315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
27415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
27515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                if (l != null) {
27615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    mListeners.remove(l);
27715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    binder.unlinkToDeath(l, 0);
27815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
27915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
28015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
28115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    };
28215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
28315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    public IGpsStatusProvider getGpsStatusProvider() {
28415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        return mGpsStatusProvider;
28515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
28615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
28729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
288105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        @Override public void onReceive(Context context, Intent intent) {
289105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            String action = intent.getAction();
290105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
29129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (action.equals(ALARM_WAKEUP)) {
29229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_WAKEUP");
29329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                startNavigating();
2940632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            } else if (action.equals(ALARM_TIMEOUT)) {
2950632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");
2960632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                hibernate();
29729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            } else if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
298105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                String state = intent.getStringExtra(Phone.STATE_KEY);
299105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                String apnName = intent.getStringExtra(Phone.DATA_APN_KEY);
300105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                String reason = intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY);
301105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
302105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                if (Config.LOGD) {
303105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    Log.d(TAG, "state: " + state +  " apnName: " + apnName + " reason: " + reason);
304105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                }
305e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                // FIXME - might not have an APN on CDMA
306375cbb47ff721a26b62385211b82a7cf26db0395Mike Lockwood                if ("CONNECTED".equals(state) && apnName != null && apnName.length() > 0) {
307e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    mAGpsApn = apnName;
308e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
309e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                        native_agps_data_conn_open(mAGpsApn);
310e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
31158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                    }
312105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                }
313105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
314105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
31529c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    };
316105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean isSupported() {
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_is_supported();
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3214e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    public GpsLocationProvider(Context context, ILocationManager locationManager) {
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
32315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mLocationManager = locationManager;
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3250528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // Create a wake lock
3260528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
3270528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
3280528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
32929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
33029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
3310632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
33229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
333105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        IntentFilter intentFilter = new IntentFilter();
33429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        intentFilter.addAction(ALARM_WAKEUP);
3350632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        intentFilter.addAction(ALARM_TIMEOUT);
336105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        intentFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
33729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        context.registerReceiver(mBroadcastReciever, intentFilter);
338105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
33958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
34058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
3412f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        // Battery statistics service to be notified when GPS turns on or off
3422f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
3432f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProperties = new Properties();
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            File file = new File(PROPERTIES_FILE);
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            FileInputStream stream = new FileInputStream(file);
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProperties.load(stream);
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stream.close();
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNtpServer = mProperties.getProperty("NTP_SERVER", null);
351e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
352a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood            String host = mProperties.getProperty("SUPL_HOST");
353e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            String portString = mProperties.getProperty("SUPL_PORT");
354a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood            if (host != null && portString != null) {
355105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                try {
356a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood                    int port = Integer.parseInt(portString);
357a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood                    native_set_agps_server(AGPS_TYPE_SUPL, host, port);
358a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood                    // use MS-Based position mode if SUPL support is enabled
359a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood                    mPositionMode = GPS_POSITION_MODE_MS_BASED;
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
365a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood            host = mProperties.getProperty("C2K_HOST");
366e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            portString = mProperties.getProperty("C2K_PORT");
367a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood            if (host != null && portString != null) {
368e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                try {
369a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood                    int port = Integer.parseInt(portString);
370a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood                    native_set_agps_server(AGPS_TYPE_C2K, host, port);
371a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood                    // use MS-Based position mode if SUPL support is enabled
372a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood                    mPositionMode = GPS_POSITION_MODE_MS_BASED;
373e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                } catch (NumberFormatException e) {
374e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse C2K_PORT: " + portString);
375105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                }
376105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to a
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * data network (e.g., the Internet), false otherwise.
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresNetwork() {
387a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood        return true;
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void updateNetworkState(int state) {
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNetworkAvailable = (state == LocationProvider.AVAILABLE);
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Config.LOGD) {
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.d(TAG, "updateNetworkState " + (mNetworkAvailable ? "available" : "unavailable"));
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNetworkAvailable && mNetworkThread != null && mEnabled) {
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // signal the network thread when the network becomes available
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNetworkThread.signal();
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
404fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     * This is called to inform us when another location provider returns a location.
405fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     * Someday we might use this for network location injection to aid the GPS
406fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     */
407fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    public void updateLocation(Location location) {
408d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        if (location.hasAccuracy()) {
409d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood            native_inject_location(location.getLatitude(), location.getLongitude(),
410d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood                    location.getAccuracy());
411d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        }
412fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    }
413fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood
414fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    /**
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to a
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * satellite-based positioning system (e.g., GPS), false
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise.
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresSatellite() {
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to an appropriate
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * cellular network (e.g., to make use of cell tower IDs), false
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise.
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresCell() {
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the use of this provider may result in a
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * monetary charge to the user, false if use is free.  It is up to
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * each provider to give accurate information.
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasMonetaryCost() {
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide altitude
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports altitude
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsAltitude() {
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide speed
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports speed
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsSpeed() {
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide bearing
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports bearing
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsBearing() {
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the power requirement for this provider.
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the power requirement for this provider, as one of the
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * constants Criteria.POWER_REQUIREMENT_*.
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getPowerRequirement() {
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Criteria.POWER_HIGH;
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the horizontal accuracy of this provider
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the accuracy of location from this provider, as one
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of the constants Criteria.ACCURACY_*.
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getAccuracy() {
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Criteria.ACCURACY_FINE;
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Enables this provider.  When enabled, calls to getStatus()
4934e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * must be handled.  Hardware may be started up
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the provider is enabled.
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized void enable() {
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Config.LOGD) Log.d(TAG, "enable");
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabled) return;
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnabled = native_init();
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabled) {
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // run event listener thread while we are enabled
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEventThread = new GpsEventThread();
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEventThread.start();
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (requiresNetwork()) {
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // run network thread for NTP and XTRA support
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mNetworkThread == null) {
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mNetworkThread = new GpsNetworkThread();
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mNetworkThread.start();
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mNetworkThread.signal();
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Failed to enable location provider");
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Disables this provider.  When disabled, calls to getStatus()
5224e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * need not be handled.  Hardware may be shut
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * down while the provider is disabled.
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized void disable() {
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Config.LOGD) Log.d(TAG, "disable");
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mEnabled) return;
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnabled = false;
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        stopNavigating();
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        native_disable();
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // make sure our event thread exits
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEventThread != null) {
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEventThread.join();
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (InterruptedException e) {
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.w(TAG, "InterruptedException when joining mEventThread");
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEventThread = null;
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNetworkThread != null) {
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNetworkThread.setDone();
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNetworkThread = null;
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
548d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood        // The GpsEventThread does not wait for the GPS to shutdown
549d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood        // so we need to report the GPS_STATUS_ENGINE_OFF event here
550d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood        if (mNavigating) {
551d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood            reportStatus(GPS_STATUS_ENGINE_OFF);
552d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood        }
553d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        native_cleanup();
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isEnabled() {
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mEnabled;
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getStatus(Bundle extras) {
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras != null) {
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            extras.putInt("satellites", mSvCount);
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatus;
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateStatus(int status, int svCount) {
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (status != mStatus || svCount != mSvCount) {
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatus = status;
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSvCount = svCount;
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationExtras.putInt("satellites", svCount);
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatusUpdateTime = SystemClock.elapsedRealtime();
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public long getStatusUpdateTime() {
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatusUpdateTime;
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void enableLocationTracking(boolean enable) {
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (enable) {
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = 0;
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            startNavigating();
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
58729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            mAlarmManager.cancel(mWakeupIntent);
5880632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            mAlarmManager.cancel(mTimeoutIntent);
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stopNavigating();
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setMinTime(long minTime) {
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Config.LOGD) Log.d(TAG, "setMinTime " + minTime);
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (minTime >= 0) {
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int interval = (int)(minTime/1000);
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (interval < 1) {
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                interval = 1;
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFixInterval = interval;
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final class Listener implements IBinder.DeathRecipient {
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IGpsStatusListener mListener;
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int mSensors = 0;
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Listener(IGpsStatusListener listener) {
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = listener;
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "GPS status listener died");
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(mListeners) {
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mListeners.remove(this);
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6232f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    public void addListener(int uid) {
6242f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        mClientUids.put(uid, 0);
6252f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (mNavigating) {
6262f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            try {
6272f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                mBatteryStats.noteStartGps(uid);
6282f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            } catch (RemoteException e) {
6292f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                Log.w(TAG, "RemoteException in addListener");
6302f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
6312f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
6322f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
6332f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
6342f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    public void removeListener(int uid) {
6352f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        mClientUids.delete(uid);
6362f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (mNavigating) {
6372f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            try {
6382f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                mBatteryStats.noteStopGps(uid);
6392f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            } catch (RemoteException e) {
6402f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                Log.w(TAG, "RemoteException in removeListener");
6412f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
6422f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
6432f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
6442f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendExtraCommand(String command, Bundle extras) {
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ("delete_aiding_data".equals(command)) {
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return deleteAidingData(extras);
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
65093bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        if ("force_time_injection".equals(command)) {
65193bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            return forceTimeInjection();
65293bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
65393bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        if ("force_xtra_injection".equals(command)) {
65493bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            if (native_supports_xtra() && mNetworkThread != null) {
65593bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                xtraDownloadRequest();
65693bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                return true;
65793bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            }
65893bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            return false;
65993bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Log.w(TAG, "sendExtraCommand: unknown command " + command);
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean deleteAidingData(Bundle extras) {
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags;
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras == null) {
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = GPS_DELETE_ALL;
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = 0;
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (flags != 0) {
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_delete_aiding_data(flags);
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
69593bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood    private boolean forceTimeInjection() {
69693bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        if (Config.LOGD) Log.d(TAG, "forceTimeInjection");
69793bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        if (mNetworkThread != null) {
69893bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            mNetworkThread.timeInjectRequest();
69993bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            return true;
70093bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
70193bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        return false;
70293bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood    }
70393bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void startNavigating() {
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStarted) {
70629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (DEBUG) Log.d(TAG, "startNavigating");
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = true;
708105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            if (!native_start(mPositionMode, false, mFixInterval)) {
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStarted = false;
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.e(TAG, "native_start failed in startNavigating()");
7110632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                return;
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
71515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
71629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            mFixCount = 0;
71729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            mFixRequestTime = System.currentTimeMillis();
7180632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
7190632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            // and our fix interval is not short
7200632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            if (mFixInterval >= NO_FIX_TIMEOUT) {
7210632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
7220632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                        SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT * 1000, mTimeoutIntent);
7230632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            }
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void stopNavigating() {
72829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (DEBUG) Log.d(TAG, "stopNavigating");
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mStarted) {
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = false;
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_stop();
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = 0;
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = LOCATION_INVALID;
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
73715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7410632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private void hibernate() {
7420632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        // stop GPS until our next fix interval arrives
7430632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        stopNavigating();
7440632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mFixCount = 0;
7450632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mTimeoutIntent);
7460632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mWakeupIntent);
7470632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        long now = SystemClock.elapsedRealtime();
7480632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
7490632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                SystemClock.elapsedRealtime() + mFixInterval * 1000, mWakeupIntent);
7500632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    }
7510632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our position.
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportLocation(int flags, double latitude, double longitude, double altitude,
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float speed, float bearing, float accuracy, long timestamp) {
75729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                " timestamp: " + timestamp);
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mLastFixTime = System.currentTimeMillis();
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // report time to first fix
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mTTFF == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = (int)(mLastFixTime - mFixRequestTime);
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "TTFF: " + mTTFF);
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // notify status listeners
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(mListeners) {
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int size = mListeners.size();
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int i = 0; i < size; i++) {
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Listener listener = mListeners.get(i);
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        listener.mListener.onFirstFix(mTTFF);
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Log.w(TAG, "RemoteException in stopNavigating");
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mListeners.remove(listener);
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // adjust for size of list changing
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        size--;
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mLocation) {
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = flags;
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLatitude(latitude);
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLongitude(longitude);
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setTime(timestamp);
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAltitude(altitude);
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAltitude();
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setSpeed(speed);
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeSpeed();
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setBearing(bearing);
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeBearing();
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAccuracy(accuracy);
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAccuracy();
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
81115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            try {
812275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood                mLocationManager.reportLocation(mLocation);
81315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            } catch (RemoteException e) {
81415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Log.e(TAG, "RemoteException calling reportLocation");
81515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
81815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mStarted && mStatus != LocationProvider.AVAILABLE) {
8190632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            mAlarmManager.cancel(mTimeoutIntent);
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is receiving fixes.
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent intent = new Intent(GPS_FIX_CHANGE_ACTION);
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(EXTRA_ENABLED, true);
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
82415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.AVAILABLE, mSvCount);
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
82629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
82729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (mFixCount++ >= MIN_FIX_COUNT && mFixInterval > 1) {
82829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (DEBUG) Log.d(TAG, "exceeded MIN_FIX_COUNT");
8290632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            hibernate();
83029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        }
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   }
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our status
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportStatus(int status) {
83729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) Log.v(TAG, "reportStatus status: " + status);
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean wasNavigating = mNavigating;
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNavigating = (status == GPS_STATUS_SESSION_BEGIN);
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (wasNavigating != mNavigating) {
8430528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (mNavigating) {
8440528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                if (DEBUG) Log.d(TAG, "Acquiring wakelock");
8450528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                 mWakeLock.acquire();
8460528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(mListeners) {
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int size = mListeners.size();
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int i = 0; i < size; i++) {
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Listener listener = mListeners.get(i);
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (mNavigating) {
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            listener.mListener.onGpsStarted();
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            listener.mListener.onGpsStopped();
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Log.w(TAG, "RemoteException in reportStatus");
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mListeners.remove(listener);
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // adjust for size of list changing
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        size--;
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8662f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            try {
8672f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                // update battery stats
8682f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                for (int i=mClientUids.size() - 1; i >= 0; i--) {
8692f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    int uid = mClientUids.keyAt(i);
8702f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    if (mNavigating) {
8712f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                        mBatteryStats.noteStartGps(uid);
8722f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    } else {
8732f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                        mBatteryStats.noteStopGps(uid);
8742f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    }
8752f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                }
8762f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            } catch (RemoteException e) {
8772f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                Log.w(TAG, "RemoteException in reportStatus");
8782f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
8792f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS has been enabled or disabled.
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent intent = new Intent(GPS_ENABLED_CHANGE_ACTION);
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(EXTRA_ENABLED, mNavigating);
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
8840528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
8850528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (!mNavigating) {
8860528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                if (DEBUG) Log.d(TAG, "Releasing wakelock");
8870528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                mWakeLock.release();
8880528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update SV info
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportSvStatus() {
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(mListeners) {
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int size = mListeners.size();
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < size; i++) {
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Listener listener = mListeners.get(i);
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs,
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSvElevations, mSvAzimuths, mSvMasks[EPHEMERIS_MASK],
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK]);
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.w(TAG, "RemoteException in reportSvInfo");
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mListeners.remove(listener);
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // adjust for size of list changing
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    size--;
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
91629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) {
91729c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            Log.v(TAG, "SV count: " + svCount +
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) +
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK]));
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < svCount; i++) {
92129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                Log.v(TAG, "sv: " + mSvs[i] +
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " snr: " + (float)mSnrs[i]/10 +
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " elev: " + mSvElevations[i] +
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " azimuth: " + mSvAzimuths[i] +
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " E") +
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " A") +
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U"));
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateStatus(mStatus, svCount);
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
93315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
9340632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT * 1000) {
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is no longer receiving fixes.
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent intent = new Intent(GPS_FIX_CHANGE_ACTION);
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(EXTRA_ENABLED, false);
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
93915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
94258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
94358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    /**
944e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood     * called from native code to update AGPS status
94558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood     */
946e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private void reportAGpsStatus(int type, int status) {
94758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        switch (status) {
948e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_REQUEST_AGPS_DATA_CONN:
94958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                 int result = mConnMgr.startUsingNetworkFeature(
95058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                        ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
95158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                if (result == Phone.APN_ALREADY_ACTIVE) {
952e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_open(mAGpsApn);
953e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
95458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else if (result == Phone.APN_REQUEST_STARTED) {
955e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
95658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else {
957e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_failed();
95858bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
95958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
960e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_RELEASE_AGPS_DATA_CONN:
961e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
96258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                    mConnMgr.stopUsingNetworkFeature(
96358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                            ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
964e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_closed();
965e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
96658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
96758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
968e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONNECTED:
969e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                // Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
97058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
971e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_DONE:
972e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                // Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
97358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
974e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_FAILED:
975e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                // Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
97658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
97758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        }
97858bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    }
97958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void xtraDownloadRequest() {
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Config.LOGD) Log.d(TAG, "xtraDownloadRequest");
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNetworkThread != null) {
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNetworkThread.xtraDownloadRequest();
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class GpsEventThread extends Thread {
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public GpsEventThread() {
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super("GpsEventThread");
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "GpsEventThread starting");
995d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood            // Exit as soon as disable() is called instead of waiting for the GPS to stop.
996d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood            while (mEnabled) {
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // this will wait for an event from the GPS,
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // which will be reported via reportLocation or reportStatus
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                native_wait_for_event();
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "GpsEventThread exiting");
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class GpsNetworkThread extends Thread {
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private long mNextNtpTime = 0;
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private long mNextXtraTime = 0;
100993bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        private boolean mTimeInjectRequested = false;
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mXtraDownloadRequested = false;
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mDone = false;
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public GpsNetworkThread() {
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super("GpsNetworkThread");
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mNetworkThreadLock) {
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!mDone) {
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    runLocked();
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void runLocked() {
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "NetworkThread starting");
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SntpClient client = new SntpClient();
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            GpsXtraDownloader xtraDownloader = null;
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (native_supports_xtra()) {
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // thread exits after disable() is called
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while (!mDone) {
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long waitTime = getWaitTime();
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                do {
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    synchronized (this) {
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        try {
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (!mNetworkAvailable) {
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (Config.LOGD) Log.d(TAG,
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        "NetworkThread wait for network");
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                wait();
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            } else if (waitTime > 0) {
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (Config.LOGD) {
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    Log.d(TAG, "NetworkThread wait for " +
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                            waitTime + "ms");
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                wait(waitTime);
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } catch (InterruptedException e) {
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (Config.LOGD) {
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                Log.d(TAG, "InterruptedException in GpsNetworkThread");
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    waitTime = getWaitTime();
1059e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                } while (!mDone && ((!mXtraDownloadRequested &&
1060a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood                        !mTimeInjectRequested && waitTime > 0)
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || !mNetworkAvailable));
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (Config.LOGD) Log.d(TAG, "NetworkThread out of wake loop");
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!mDone) {
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (mNtpServer != null &&
106693bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                            (mTimeInjectRequested || mNextNtpTime <= System.currentTimeMillis())) {
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (Config.LOGD) {
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            Log.d(TAG, "Requesting time from NTP server " + mNtpServer);
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
107093bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                        mTimeInjectRequested = false;
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (client.requestTime(mNtpServer, 10000)) {
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            long time = client.getNtpTime();
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            long timeReference = client.getNtpTimeReference();
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            int certainty = (int)(client.getRoundTripTime()/2);
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (Config.LOGD) Log.d(TAG, "calling native_inject_time: " +
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    time + " reference: " + timeReference
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    + " certainty: " + certainty);
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            native_inject_time(time, timeReference, certainty);
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mNextNtpTime = System.currentTimeMillis() + NTP_INTERVAL;
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (Config.LOGD) Log.d(TAG, "requestTime failed");
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mNextNtpTime = System.currentTimeMillis() + RETRY_INTERVAL;
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if ((mXtraDownloadRequested ||
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (mNextXtraTime > 0 && mNextXtraTime <= System.currentTimeMillis()))
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            && xtraDownloader != null) {
109193bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                        mXtraDownloadRequested = false;
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        byte[] data = xtraDownloader.downloadXtraData();
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (data != null) {
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (Config.LOGD) {
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                Log.d(TAG, "calling native_inject_xtra_data");
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            native_inject_xtra_data(data, data.length);
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mNextXtraTime = 0;
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mNextXtraTime = System.currentTimeMillis() + RETRY_INTERVAL;
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "NetworkThread exiting");
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized void xtraDownloadRequest() {
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mXtraDownloadRequested = true;
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notify();
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
111393bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        synchronized void timeInjectRequest() {
111493bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            mTimeInjectRequested = true;
111593bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            notify();
111693bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
111793bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized void signal() {
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notify();
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized void setDone() {
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "stopping NetworkThread");
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDone = true;
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notify();
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private long getWaitTime() {
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long now = System.currentTimeMillis();
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long waitTime = Long.MAX_VALUE;
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mNtpServer != null) {
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                waitTime = mNextNtpTime - now;
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mNextXtraTime != 0) {
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long xtraWaitTime = mNextXtraTime - now;
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (xtraWaitTime < waitTime) {
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    waitTime = xtraWaitTime;
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (waitTime < 0) {
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                waitTime = 0;
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return waitTime;
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for GPS SV statistics
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int MAX_SVS = 32;
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int EPHEMERIS_MASK = 0;
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int ALMANAC_MASK = 1;
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int USED_FOR_FIX_MASK = 2;
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // preallocated arrays, to avoid memory allocation in reportStatus()
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvs[] = new int[MAX_SVS];
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSnrs[] = new float[MAX_SVS];
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvElevations[] = new float[MAX_SVS];
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvAzimuths[] = new float[MAX_SVS];
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvMasks[] = new int[3];
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvCount;
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static { class_init_native(); }
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native void class_init_native();
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native boolean native_is_supported();
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_init();
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_disable();
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_cleanup();
1168105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private native boolean native_start(int positionMode, boolean singleFix, int fixInterval);
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_stop();
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_set_fix_frequency(int fixFrequency);
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_delete_aiding_data(int flags);
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_wait_for_event();
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // returns number of SVs
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // mask[0] is ephemeris mask and mask[1] is almanac mask
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native int native_read_sv_status(int[] svs, float[] snrs,
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] elevations, float[] azimuths, int[] masks);
1177d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood    private native void native_inject_location(double latitude, double longitude, float accuracy);
1178d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // XTRA Support
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_time(long time, long timeReference, int uncertainty);
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_supports_xtra();
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_xtra_data(byte[] data, int length);
1183105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1184e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // AGPS Support
1185e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_open(String apn);
1186e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_closed();
1187e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_failed();
1188a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood    private native void native_set_agps_server(int type, String hostname, int port);
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1190