GpsLocationProvider.java revision dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9
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;
3022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport android.location.INetInitiatedListener;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Location;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationManager;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationProvider;
3458bda987665af759c379cd494ff4873ac61acf29Mike Lockwoodimport android.net.ConnectivityManager;
3503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwoodimport android.net.NetworkInfo;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.SntpClient;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
390528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwoodimport android.os.PowerManager;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
412f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport android.os.ServiceManager;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
43bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwoodimport android.provider.Settings;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Config;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
462f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport android.util.SparseIntArray;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
482f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwoodimport com.android.internal.app.IBatteryStats;
49105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport com.android.internal.telephony.Phone;
5022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport com.android.internal.location.GpsNetInitiatedHandler;
5122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
52105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileInputStream;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
5622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport java.io.StringBufferInputStream;
57105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport java.net.InetAddress;
58105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Projectimport java.net.UnknownHostException;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Properties;
6122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport java.util.Map.Entry;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A GPS implementation of LocationProvider used by LocationManager.
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
6815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwoodpublic class GpsLocationProvider extends ILocationProvider.Stub {
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "GpsLocationProvider";
7129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
7229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private static final boolean DEBUG = true;
7329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private static final boolean VERBOSE = false;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcast intent action indicating that the GPS has either been
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * enabled or disabled. An intent extra provides this state as a boolean,
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * where {@code true} means enabled.
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #EXTRA_ENABLED
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String GPS_ENABLED_CHANGE_ACTION =
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "android.location.GPS_ENABLED_CHANGE";
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Broadcast intent action indicating that the GPS has either started or
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * stopped receiving GPS fixes. An intent extra provides this state as a
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * boolean, where {@code true} means that the GPS is actively receiving fixes.
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #EXTRA_ENABLED
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String GPS_FIX_CHANGE_ACTION =
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "android.location.GPS_FIX_CHANGE";
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The lookup key for a boolean that indicates whether GPS is enabled or
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * disabled. {@code true} means GPS is enabled. Retrieve it with
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link android.content.Intent#getBooleanExtra(String,boolean)}.
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@hide}
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String EXTRA_ENABLED = "enabled";
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
106105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    // these need to match GpsPositionMode enum in gps.h
107105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_STANDALONE = 0;
108105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_MS_BASED = 1;
109105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
110105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these need to match GpsStatusValue defines in gps.h
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_NONE = 0;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_SESSION_BEGIN = 1;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_SESSION_END = 2;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_ENGINE_ON = 3;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_STATUS_ENGINE_OFF = 4;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
118e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // these need to match GpsApgsStatusValue defines in gps.h
119e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    /** AGPS status event values. */
120e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
121e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
122e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONNECTED = 3;
123e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONN_DONE = 4;
124e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
12558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // these need to match GpsLocationFlags enum in gps.h
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_INVALID = 0;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_LAT_LONG = 1;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_ALTITUDE = 2;
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_SPEED = 4;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_BEARING = 8;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int LOCATION_HAS_ACCURACY = 16;
133e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
134e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood// IMPORTANT - the GPS_DELETE_* symbols here must match constants in gps.h
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_EPHEMERIS = 0x0001;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_ALMANAC = 0x0002;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_POSITION = 0x0004;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_TIME = 0x0008;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_IONO = 0x0010;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_UTC = 0x0020;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_HEALTH = 0x0040;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SVDIR = 0x0080;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SVSTEER = 0x0100;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_SADATA = 0x0200;
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_RTI = 0x0400;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int GPS_DELETE_ALL = 0xFFFF;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
149e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // these need to match AGpsType enum in gps.h
150e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_TYPE_SUPL = 1;
151e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_TYPE_C2K = 2;
152e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
153e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // for mAGpsDataConnectionState
154e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
155e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_OPENING = 1;
156e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private static final int AGPS_DATA_CONNECTION_OPEN = 2;
15758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String PROPERTIES_FILE = "/etc/gps.conf";
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mLocationFlags = LOCATION_INVALID;
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current status
16315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time for last status update
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mStatusUpdateTime = SystemClock.elapsedRealtime();
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // turn off GPS fix icon if we haven't received a fix in 10 seconds
1690632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private static final long RECENT_FIX_TIMEOUT = 10;
17029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
17129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    // number of fixes to receive before disabling GPS
17229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private static final int MIN_FIX_COUNT = 10;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1740632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    // stop trying if we do not receive a fix within 60 seconds
1750632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private static final int NO_FIX_TIMEOUT = 60;
1760632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we are enabled
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mEnabled;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we have network connectivity
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNetworkAvailable;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if GPS is navigating
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mNavigating;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // requested frequency of fixes, in seconds
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mFixInterval = 1;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    // number of fixes we have received since we started navigating
19029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private int mFixCount;
19129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // true if we started navigation
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mStarted;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for calculating time to first fix
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mFixRequestTime = 0;
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time to first fix for most recent session
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mTTFF = 0;
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // time we received our last fix
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long mLastFixTime;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // properties loaded from PROPERTIES_FILE
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Properties mProperties;
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String mNtpServer;
205734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private String mSuplServerHost;
206734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private int mSuplServerPort;
207734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private String mC2KServerHost;
208734d6031a662a275ec68627bd1258159041d44deMike Lockwood    private int mC2KServerPort;
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final Context mContext;
21115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final ILocationManager mLocationManager;
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Bundle mLocationExtras = new Bundle();
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<Listener> mListeners = new ArrayList<Listener>();
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private GpsEventThread mEventThread;
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private GpsNetworkThread mNetworkThread;
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Object mNetworkThreadLock = new Object();
218105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
219e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private String mAGpsApn;
220e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private int mAGpsDataConnectionState;
2212f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final ConnectivityManager mConnMgr;
22222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private final GpsNetInitiatedHandler mNIHandler;
2232f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
2240528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    // Wakelocks
2250528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final static String WAKELOCK_KEY = "GpsLocationProvider";
2260528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final PowerManager.WakeLock mWakeLock;
2270528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
22829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    // Alarms
22929c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
2300632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
23129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final AlarmManager mAlarmManager;
23229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final PendingIntent mWakeupIntent;
2330632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private final PendingIntent mTimeoutIntent;
23429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
2352f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final IBatteryStats mBatteryStats;
2362f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final SparseIntArray mClientUids = new SparseIntArray();
237105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // how often to request NTP time, in milliseconds
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current setting 4 hours
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final long NTP_INTERVAL = 4*60*60*1000;
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // how long to wait if we have a network error in NTP or XTRA downloading
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // current setting - 5 minutes
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final long RETRY_INTERVAL = 5*60*1000;
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
24615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
24715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
24815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
24915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
25015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
25115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            synchronized(mListeners) {
25215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
25315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
25415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size; i++) {
25515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
25615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
25715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        // listener already added
25815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        return;
25915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
26015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
26115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
26215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = new Listener(listener);
26315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                binder.linkToDeath(l, 0);
26415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                mListeners.add(l);
26515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
26615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
26715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
26815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        public void removeGpsStatusListener(IGpsStatusListener listener) {
26915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (listener == null) {
27015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                throw new NullPointerException("listener is null in addGpsStatusListener");
27115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
27215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
27315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            synchronized(mListeners) {
27415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                IBinder binder = listener.asBinder();
27515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Listener l = null;
27615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                int size = mListeners.size();
27715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                for (int i = 0; i < size && l == null; i++) {
27815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    Listener test = mListeners.get(i);
27915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    if (binder.equals(test.mListener.asBinder())) {
28015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        l = test;
28115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    }
28215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
28315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
28415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                if (l != null) {
28515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    mListeners.remove(l);
28615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    binder.unlinkToDeath(l, 0);
28715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                }
28815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
28915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        }
29015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    };
29115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
29215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    public IGpsStatusProvider getGpsStatusProvider() {
29315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        return mGpsStatusProvider;
29415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
29515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
29629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
297105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        @Override public void onReceive(Context context, Intent intent) {
298105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            String action = intent.getAction();
299105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
30029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (action.equals(ALARM_WAKEUP)) {
30129c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_WAKEUP");
30229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                startNavigating();
3030632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            } else if (action.equals(ALARM_TIMEOUT)) {
3040632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");
3050632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                hibernate();
306105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
307105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
30829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood    };
309105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean isSupported() {
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_is_supported();
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3144e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    public GpsLocationProvider(Context context, ILocationManager locationManager) {
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
31615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mLocationManager = locationManager;
31722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        mNIHandler= new GpsNetInitiatedHandler(context, this);
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3190528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // Create a wake lock
3200528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
3210528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
3220528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
32329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
32429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
3250632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
32629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
327105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        IntentFilter intentFilter = new IntentFilter();
32829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        intentFilter.addAction(ALARM_WAKEUP);
3290632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        intentFilter.addAction(ALARM_TIMEOUT);
33029c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        context.registerReceiver(mBroadcastReciever, intentFilter);
331105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
33258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
33358bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
3342f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        // Battery statistics service to be notified when GPS turns on or off
3352f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
3362f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProperties = new Properties();
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            File file = new File(PROPERTIES_FILE);
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            FileInputStream stream = new FileInputStream(file);
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProperties.load(stream);
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stream.close();
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNtpServer = mProperties.getProperty("NTP_SERVER", null);
344e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
345734d6031a662a275ec68627bd1258159041d44deMike Lockwood            mSuplServerHost = mProperties.getProperty("SUPL_HOST");
346e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            String portString = mProperties.getProperty("SUPL_PORT");
347734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mSuplServerHost != null && portString != null) {
348105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                try {
349734d6031a662a275ec68627bd1258159041d44deMike Lockwood                    mSuplServerPort = Integer.parseInt(portString);
350105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                } catch (NumberFormatException e) {
351e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
352e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                }
353e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            }
354e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood
355734d6031a662a275ec68627bd1258159041d44deMike Lockwood            mC2KServerHost = mProperties.getProperty("C2K_HOST");
356e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            portString = mProperties.getProperty("C2K_PORT");
357734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mC2KServerHost != null && portString != null) {
358e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                try {
359734d6031a662a275ec68627bd1258159041d44deMike Lockwood                    mC2KServerPort = Integer.parseInt(portString);
360e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                } catch (NumberFormatException e) {
361e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    Log.e(TAG, "unable to parse C2K_PORT: " + portString);
362105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                }
363105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to a
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * data network (e.g., the Internet), false otherwise.
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresNetwork() {
374a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood        return true;
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
37703d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood    public void updateNetworkState(int state, NetworkInfo info) {
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNetworkAvailable = (state == LocationProvider.AVAILABLE);
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Config.LOGD) {
38103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            Log.d(TAG, "updateNetworkState " + (mNetworkAvailable ? "available" : "unavailable")
38203d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                + " info: " + info);
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
38403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood
38503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood        if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL
38603d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
38703d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            String apnName = info.getExtraInfo();
38803d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            if (mNetworkAvailable && apnName != null && apnName.length() > 0) {
38903d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsApn = apnName;
39003d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                if (DEBUG) Log.d(TAG, "call native_agps_data_conn_open");
39103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                native_agps_data_conn_open(apnName);
39203d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
39303d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            } else {
39403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                if (DEBUG) Log.d(TAG, "call native_agps_data_conn_failed");
39503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsApn = null;
39603d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
39703d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                native_agps_data_conn_failed();
39803d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            }
39903d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood        }
40003d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNetworkAvailable && mNetworkThread != null && mEnabled) {
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // signal the network thread when the network becomes available
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNetworkThread.signal();
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
408fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     * This is called to inform us when another location provider returns a location.
409fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     * Someday we might use this for network location injection to aid the GPS
410fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood     */
411fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    public void updateLocation(Location location) {
412d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        if (location.hasAccuracy()) {
413d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood            native_inject_location(location.getLatitude(), location.getLongitude(),
414d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood                    location.getAccuracy());
415d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood        }
416fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    }
417fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood
418fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood    /**
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to a
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * satellite-based positioning system (e.g., GPS), false
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise.
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresSatellite() {
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider requires access to an appropriate
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * cellular network (e.g., to make use of cell tower IDs), false
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * otherwise.
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean requiresCell() {
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the use of this provider may result in a
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * monetary charge to the user, false if use is free.  It is up to
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * each provider to give accurate information.
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasMonetaryCost() {
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide altitude
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports altitude
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsAltitude() {
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide speed
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports speed
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsSpeed() {
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the provider is able to provide bearing
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, false otherwise.  A provider that reports bearing
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * under most circumstances but may occassionally not report it
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * should return true.
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean supportsBearing() {
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the power requirement for this provider.
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the power requirement for this provider, as one of the
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * constants Criteria.POWER_REQUIREMENT_*.
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getPowerRequirement() {
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Criteria.POWER_HIGH;
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the horizontal accuracy of this provider
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the accuracy of location from this provider, as one
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of the constants Criteria.ACCURACY_*.
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getAccuracy() {
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Criteria.ACCURACY_FINE;
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Enables this provider.  When enabled, calls to getStatus()
4974e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * must be handled.  Hardware may be started up
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the provider is enabled.
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized void enable() {
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Config.LOGD) Log.d(TAG, "enable");
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabled) return;
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnabled = native_init();
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabled) {
506734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mSuplServerHost != null) {
507734d6031a662a275ec68627bd1258159041d44deMike Lockwood                native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
508734d6031a662a275ec68627bd1258159041d44deMike Lockwood            }
509734d6031a662a275ec68627bd1258159041d44deMike Lockwood            if (mC2KServerHost != null) {
510734d6031a662a275ec68627bd1258159041d44deMike Lockwood                native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
511734d6031a662a275ec68627bd1258159041d44deMike Lockwood            }
512734d6031a662a275ec68627bd1258159041d44deMike Lockwood
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // run event listener thread while we are enabled
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEventThread = new GpsEventThread();
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEventThread.start();
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (requiresNetwork()) {
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // run network thread for NTP and XTRA support
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mNetworkThread == null) {
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mNetworkThread = new GpsNetworkThread();
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mNetworkThread.start();
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mNetworkThread.signal();
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Failed to enable location provider");
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Disables this provider.  When disabled, calls to getStatus()
5334e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood     * need not be handled.  Hardware may be shut
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * down while the provider is disabled.
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public synchronized void disable() {
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Config.LOGD) Log.d(TAG, "disable");
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mEnabled) return;
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mEnabled = false;
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        stopNavigating();
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        native_disable();
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // make sure our event thread exits
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEventThread != null) {
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEventThread.join();
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (InterruptedException e) {
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.w(TAG, "InterruptedException when joining mEventThread");
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEventThread = null;
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNetworkThread != null) {
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNetworkThread.setDone();
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNetworkThread = null;
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
559d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood        // The GpsEventThread does not wait for the GPS to shutdown
560d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood        // so we need to report the GPS_STATUS_ENGINE_OFF event here
561d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood        if (mNavigating) {
562d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood            reportStatus(GPS_STATUS_ENGINE_OFF);
563d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood        }
564d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        native_cleanup();
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isEnabled() {
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mEnabled;
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getStatus(Bundle extras) {
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras != null) {
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            extras.putInt("satellites", mSvCount);
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatus;
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateStatus(int status, int svCount) {
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (status != mStatus || svCount != mSvCount) {
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatus = status;
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSvCount = svCount;
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationExtras.putInt("satellites", svCount);
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStatusUpdateTime = SystemClock.elapsedRealtime();
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public long getStatusUpdateTime() {
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStatusUpdateTime;
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void enableLocationTracking(boolean enable) {
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (enable) {
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = 0;
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            startNavigating();
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
59829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            mAlarmManager.cancel(mWakeupIntent);
5990632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            mAlarmManager.cancel(mTimeoutIntent);
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stopNavigating();
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setMinTime(long minTime) {
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Config.LOGD) Log.d(TAG, "setMinTime " + minTime);
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (minTime >= 0) {
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int interval = (int)(minTime/1000);
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (interval < 1) {
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                interval = 1;
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFixInterval = interval;
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final class Listener implements IBinder.DeathRecipient {
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IGpsStatusListener mListener;
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int mSensors = 0;
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Listener(IGpsStatusListener listener) {
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = listener;
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "GPS status listener died");
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(mListeners) {
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mListeners.remove(this);
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
631fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu            if (mListener != null) {
632fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu                mListener.asBinder().unlinkToDeath(this, 0);
633fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu            }
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6372f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    public void addListener(int uid) {
6382e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
6392e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mClientUids.indexOfKey(uid) >= 0) {
6402e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                // Shouldn't be here -- already have this uid.
6412e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                Log.w(TAG, "Duplicate add listener for uid " + uid);
6422e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                return;
6432e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            }
6442e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            mClientUids.put(uid, 0);
6452e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mNavigating) {
6462e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
6472e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    mBatteryStats.noteStartGps(uid);
6482e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
6492e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in addListener");
6502e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                }
6512f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
6522f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
6532f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
6542f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
6552f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    public void removeListener(int uid) {
6562e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
6572e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mClientUids.indexOfKey(uid) < 0) {
6582e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                // Shouldn't be here -- don't have this uid.
6592e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                Log.w(TAG, "Unneeded remove listener for uid " + uid);
6602e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                return;
6612e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            }
6622e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            mClientUids.delete(uid);
6632e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            if (mNavigating) {
6642e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
6652e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    mBatteryStats.noteStopGps(uid);
6662e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
6672e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in removeListener");
6682e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                }
6692f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
6702f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
6712f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
6722f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendExtraCommand(String command, Bundle extras) {
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ("delete_aiding_data".equals(command)) {
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return deleteAidingData(extras);
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
67893bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        if ("force_time_injection".equals(command)) {
67993bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            return forceTimeInjection();
68093bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
68193bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        if ("force_xtra_injection".equals(command)) {
68293bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            if (native_supports_xtra() && mNetworkThread != null) {
68393bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                xtraDownloadRequest();
68493bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                return true;
68593bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            }
68693bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            return false;
68793bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Log.w(TAG, "sendExtraCommand: unknown command " + command);
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean deleteAidingData(Bundle extras) {
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags;
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (extras == null) {
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = GPS_DELETE_ALL;
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags = 0;
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (flags != 0) {
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_delete_aiding_data(flags);
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
72393bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood    private boolean forceTimeInjection() {
72493bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        if (Config.LOGD) Log.d(TAG, "forceTimeInjection");
72593bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        if (mNetworkThread != null) {
72693bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            mNetworkThread.timeInjectRequest();
72793bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            return true;
72893bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
72993bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        return false;
73093bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood    }
73193bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void startNavigating() {
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStarted) {
73429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (DEBUG) Log.d(TAG, "startNavigating");
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = true;
736bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood            int positionMode;
7372bb99d1e2f0296dd8b09a451575f70f49da30a1bMike Lockwood            if (Settings.Secure.getInt(mContext.getContentResolver(),
738660bbfcc54d48d5d32e64da683c76b9c372c19b1Mike Lockwood                    Settings.Secure.ASSISTED_GPS_ENABLED, 1) != 0) {
739bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood                positionMode = GPS_POSITION_MODE_MS_BASED;
740bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood            } else {
741bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood                positionMode = GPS_POSITION_MODE_STANDALONE;
742bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood            }
743bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood
744bcab8df83e6e769a7cbcc742e72b47d665998793Mike Lockwood            if (!native_start(positionMode, false, mFixInterval)) {
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStarted = false;
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.e(TAG, "native_start failed in startNavigating()");
7470632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                return;
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
75115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
75229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            mFixCount = 0;
75329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            mFixRequestTime = System.currentTimeMillis();
7540632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
7550632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            // and our fix interval is not short
7560632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            if (mFixInterval >= NO_FIX_TIMEOUT) {
7570632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
7580632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                        SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT * 1000, mTimeoutIntent);
7590632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            }
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void stopNavigating() {
76429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (DEBUG) Log.d(TAG, "stopNavigating");
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mStarted) {
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStarted = false;
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_stop();
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = 0;
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastFixTime = 0;
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = LOCATION_INVALID;
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // reset SV count to zero
77315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7770632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    private void hibernate() {
7780632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        // stop GPS until our next fix interval arrives
7790632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        stopNavigating();
7800632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mFixCount = 0;
7810632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mTimeoutIntent);
7820632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.cancel(mWakeupIntent);
7830632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        long now = SystemClock.elapsedRealtime();
7840632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
7850632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood                SystemClock.elapsedRealtime() + mFixInterval * 1000, mWakeupIntent);
7860632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood    }
7870632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our position.
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportLocation(int flags, double latitude, double longitude, double altitude,
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float speed, float bearing, float accuracy, long timestamp) {
79329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                " timestamp: " + timestamp);
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mLastFixTime = System.currentTimeMillis();
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // report time to first fix
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mTTFF == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTTFF = (int)(mLastFixTime - mFixRequestTime);
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "TTFF: " + mTTFF);
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // notify status listeners
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized(mListeners) {
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int size = mListeners.size();
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int i = 0; i < size; i++) {
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Listener listener = mListeners.get(i);
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        listener.mListener.onFirstFix(mTTFF);
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Log.w(TAG, "RemoteException in stopNavigating");
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mListeners.remove(listener);
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // adjust for size of list changing
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        size--;
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mLocation) {
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocationFlags = flags;
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLatitude(latitude);
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setLongitude(longitude);
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setTime(timestamp);
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAltitude(altitude);
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAltitude();
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setSpeed(speed);
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeSpeed();
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setBearing(bearing);
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeBearing();
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.setAccuracy(accuracy);
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLocation.removeAccuracy();
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
84715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            try {
848275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood                mLocationManager.reportLocation(mLocation);
84915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            } catch (RemoteException e) {
85015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Log.e(TAG, "RemoteException calling reportLocation");
85115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
85415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mStarted && mStatus != LocationProvider.AVAILABLE) {
8550632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            mAlarmManager.cancel(mTimeoutIntent);
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is receiving fixes.
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent intent = new Intent(GPS_FIX_CHANGE_ACTION);
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(EXTRA_ENABLED, true);
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
86015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.AVAILABLE, mSvCount);
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
86229c84340a14e70419449628ab193d11b7a609e9aMike Lockwood
86329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (mFixCount++ >= MIN_FIX_COUNT && mFixInterval > 1) {
86429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            if (DEBUG) Log.d(TAG, "exceeded MIN_FIX_COUNT");
8650632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            hibernate();
86629c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        }
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   }
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update our status
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportStatus(int status) {
87329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) Log.v(TAG, "reportStatus status: " + status);
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8752e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn        synchronized(mListeners) {
8762e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            boolean wasNavigating = mNavigating;
8772e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn            mNavigating = (status == GPS_STATUS_SESSION_BEGIN);
878dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood
879dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood            if (mNavigating && !mWakeLock.isHeld()) {
8800528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                if (DEBUG) Log.d(TAG, "Acquiring wakelock");
8810528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                 mWakeLock.acquire();
8820528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
883dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood
884dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood            if (wasNavigating != mNavigating) {
885dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                int size = mListeners.size();
886dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                for (int i = 0; i < size; i++) {
887dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    Listener listener = mListeners.get(i);
888dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    try {
889dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        if (mNavigating) {
890dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            listener.mListener.onGpsStarted();
891dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        } else {
892dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            listener.mListener.onGpsStopped();
893dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        }
894dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    } catch (RemoteException e) {
895dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        Log.w(TAG, "RemoteException in reportStatus");
896dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        mListeners.remove(listener);
897dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        // adjust for size of list changing
898dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        size--;
899dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    }
900dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                }
901dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood
9022e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                try {
903dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    // update battery stats
904dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                    for (int i=mClientUids.size() - 1; i >= 0; i--) {
905dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        int uid = mClientUids.keyAt(i);
906dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        if (mNavigating) {
907dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            mBatteryStats.noteStartGps(uid);
908dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        } else {
909dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                            mBatteryStats.noteStopGps(uid);
910dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                        }
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9122e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                } catch (RemoteException e) {
9132e418428987132ea66533cbc05f9c526eb59519aDianne Hackborn                    Log.w(TAG, "RemoteException in reportStatus");
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
916dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                // send an intent to notify that the GPS has been enabled or disabled.
917dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                Intent intent = new Intent(GPS_ENABLED_CHANGE_ACTION);
918dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                intent.putExtra(EXTRA_ENABLED, mNavigating);
919dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood                mContext.sendBroadcast(intent);
9202f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
9212f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
922dbd6fd8ebb60dd7bb243f9c78db994a8e7e5b5c9Mike Lockwood            if (status == GPS_STATUS_ENGINE_OFF && mWakeLock.isHeld()) {
9230528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                if (DEBUG) Log.d(TAG, "Releasing wakelock");
9240528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                mWakeLock.release();
9250528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * called from native code to update SV info
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void reportSvStatus() {
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(mListeners) {
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int size = mListeners.size();
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < size; i++) {
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Listener listener = mListeners.get(i);
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs,
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSvElevations, mSvAzimuths, mSvMasks[EPHEMERIS_MASK],
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK]);
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.w(TAG, "RemoteException in reportSvInfo");
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mListeners.remove(listener);
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // adjust for size of list changing
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    size--;
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
95329c84340a14e70419449628ab193d11b7a609e9aMike Lockwood        if (VERBOSE) {
95429c84340a14e70419449628ab193d11b7a609e9aMike Lockwood            Log.v(TAG, "SV count: " + svCount +
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) +
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK]));
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < svCount; i++) {
95829c84340a14e70419449628ab193d11b7a609e9aMike Lockwood                Log.v(TAG, "sv: " + mSvs[i] +
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " snr: " + (float)mSnrs[i]/10 +
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " elev: " + mSvElevations[i] +
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " azimuth: " + mSvAzimuths[i] +
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " E") +
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "  " : " A") +
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U"));
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateStatus(mStatus, svCount);
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
97015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
9710632ca7bbea5dbd89a584cc3cd6a0630a767e94bMike Lockwood            System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT * 1000) {
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // send an intent to notify that the GPS is no longer receiving fixes.
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Intent intent = new Intent(GPS_FIX_CHANGE_ACTION);
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            intent.putExtra(EXTRA_ENABLED, false);
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.sendBroadcast(intent);
97615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
97958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
98058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    /**
981e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood     * called from native code to update AGPS status
98258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood     */
983e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private void reportAGpsStatus(int type, int status) {
98458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        switch (status) {
985e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_REQUEST_AGPS_DATA_CONN:
98658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                 int result = mConnMgr.startUsingNetworkFeature(
98758bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                        ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
98858bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                if (result == Phone.APN_ALREADY_ACTIVE) {
989b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    if (mAGpsApn != null) {
990b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        native_agps_data_conn_open(mAGpsApn);
991b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
992b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    } else {
993b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        Log.e(TAG, "mAGpsApn not set when receiving Phone.APN_ALREADY_ACTIVE");
994b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                        native_agps_data_conn_failed();
995b362a9ab91bb4c05ef1d5c4e7019499257c7f849Mike Lockwood                    }
99658bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else if (result == Phone.APN_REQUEST_STARTED) {
997e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
99858bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                } else {
999e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_failed();
100058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
100158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1002e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_RELEASE_AGPS_DATA_CONN:
1003e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
100458bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                    mConnMgr.stopUsingNetworkFeature(
100558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                            ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
1006e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    native_agps_data_conn_closed();
1007e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
100858bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                }
100958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1010e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONNECTED:
1011e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                // Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
101258bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1013e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_DONE:
1014e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                // Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
101558bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
1016e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood            case GPS_AGPS_DATA_CONN_FAILED:
1017e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                // Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
101858bda987665af759c379cd494ff4873ac61acf29Mike Lockwood                break;
101958bda987665af759c379cd494ff4873ac61acf29Mike Lockwood        }
102058bda987665af759c379cd494ff4873ac61acf29Mike Lockwood    }
102158bda987665af759c379cd494ff4873ac61acf29Mike Lockwood
1022b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    /**
1023b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood     * called from native code to report NMEA data received
1024b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood     */
1025b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    private void reportNmea(int index, long timestamp) {
1026b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood        synchronized(mListeners) {
1027b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            int size = mListeners.size();
1028b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            if (size > 0) {
1029b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                // don't bother creating the String if we have no listeners
1030b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                int length = native_read_nmea(index, mNmeaBuffer, mNmeaBuffer.length);
1031b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                String nmea = new String(mNmeaBuffer, 0, length);
1032b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood
1033b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                for (int i = 0; i < size; i++) {
1034b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    Listener listener = mListeners.get(i);
1035b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    try {
1036b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        listener.mListener.onNmeaReceived(timestamp, nmea);
1037b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    } catch (RemoteException e) {
1038b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        Log.w(TAG, "RemoteException in reportNmea");
1039b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        mListeners.remove(listener);
1040b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        // adjust for size of list changing
1041b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                        size--;
1042b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                    }
1043b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood                }
1044b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood            }
1045b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood        }
1046b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    }
1047b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void xtraDownloadRequest() {
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Config.LOGD) Log.d(TAG, "xtraDownloadRequest");
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNetworkThread != null) {
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNetworkThread.xtraDownloadRequest();
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
105522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    //=============================================================
105622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // NI Client support
105722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie	//=============================================================
105822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
105922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    	// Sends a response for an NI reqeust to HAL.
106022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    	public boolean sendNiResponse(int notificationId, int userResponse)
106122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    	{
106222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	// TODO Add Permission check
106322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
106422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    		StringBuilder extrasBuf = new StringBuilder();
106522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
106622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    		if (Config.LOGD) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
106722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    				", response: " + userResponse);
106822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
106922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    		native_send_ni_response(notificationId, userResponse);
107022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
107122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    		return true;
107222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    	}
107322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    };
107422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
107522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    public INetInitiatedListener getNetInitiatedListener() {
107622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        return mNetInitiatedListener;
107722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    }
107822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
107922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // Called by JNI function to report an NI request.
108022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie	@SuppressWarnings("deprecation")
108122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie	public void reportNiNotification(
108222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int notificationId,
108322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int niType,
108422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int notifyFlags,
108522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int timeout,
108622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int defaultResponse,
108722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	String requestorId,
108822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	String text,
108922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int requestorIdEncoding,
109022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	int textEncoding,
109122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        	String extras  // Encoded extra data
109222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        )
109322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie	{
109422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		Log.i(TAG, "reportNiNotification: entered");
109522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		Log.i(TAG, "notificationId: " + notificationId +
109622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", niType: " + niType +
109722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", notifyFlags: " + notifyFlags +
109822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", timeout: " + timeout +
109922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", defaultResponse: " + defaultResponse);
110022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
110122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		Log.i(TAG, "requestorId: " + requestorId +
110222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", text: " + text +
110322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", requestorIdEncoding: " + requestorIdEncoding +
110422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie				", textEncoding: " + textEncoding);
110522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
110622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		GpsNiNotification notification = new GpsNiNotification();
110722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
110822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.notificationId = notificationId;
110922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.niType = niType;
111022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
111122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
111222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
111322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.timeout = timeout;
111422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.defaultResponse = defaultResponse;
111522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.requestorId = requestorId;
111622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.text = text;
111722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.requestorIdEncoding = requestorIdEncoding;
111822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.textEncoding = textEncoding;
111922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
112022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		// Process extras, assuming the format is
112122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		// one of more lines of "key = value"
112222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		Bundle bundle = new Bundle();
112322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
112422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		if (extras == null) extras = "";
112522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		Properties extraProp = new Properties();
112622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
112722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		try {
112822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie			extraProp.load(new StringBufferInputStream(extras));
112922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		}
113022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		catch (IOException e)
113122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		{
113222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie			Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
113322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		}
113422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
113522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		for (Entry<Object, Object> ent : extraProp.entrySet())
113622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		{
113722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie			bundle.putString((String) ent.getKey(), (String) ent.getValue());
113822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		}
113922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
114022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		notification.extras = bundle;
114122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
114222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie		mNIHandler.handleNiNotification(notification);
114322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie	}
114422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class GpsEventThread extends Thread {
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public GpsEventThread() {
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super("GpsEventThread");
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "GpsEventThread starting");
1153d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood            // Exit as soon as disable() is called instead of waiting for the GPS to stop.
1154d654f9f727b415b153c7190832db4b65f6943f32Mike Lockwood            while (mEnabled) {
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // this will wait for an event from the GPS,
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // which will be reported via reportLocation or reportStatus
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                native_wait_for_event();
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "GpsEventThread exiting");
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class GpsNetworkThread extends Thread {
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private long mNextNtpTime = 0;
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private long mNextXtraTime = 0;
116793bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        private boolean mTimeInjectRequested = false;
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mXtraDownloadRequested = false;
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private boolean mDone = false;
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public GpsNetworkThread() {
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super("GpsNetworkThread");
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mNetworkThreadLock) {
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!mDone) {
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    runLocked();
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void runLocked() {
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "NetworkThread starting");
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            SntpClient client = new SntpClient();
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            GpsXtraDownloader xtraDownloader = null;
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (native_supports_xtra()) {
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // thread exits after disable() is called
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while (!mDone) {
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long waitTime = getWaitTime();
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                do {
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    synchronized (this) {
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        try {
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (!mNetworkAvailable) {
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (Config.LOGD) Log.d(TAG,
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        "NetworkThread wait for network");
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                wait();
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            } else if (waitTime > 0) {
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (Config.LOGD) {
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    Log.d(TAG, "NetworkThread wait for " +
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                            waitTime + "ms");
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                wait(waitTime);
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } catch (InterruptedException e) {
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (Config.LOGD) {
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                Log.d(TAG, "InterruptedException in GpsNetworkThread");
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    waitTime = getWaitTime();
1217e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood                } while (!mDone && ((!mXtraDownloadRequested &&
1218a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood                        !mTimeInjectRequested && waitTime > 0)
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || !mNetworkAvailable));
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (Config.LOGD) Log.d(TAG, "NetworkThread out of wake loop");
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!mDone) {
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (mNtpServer != null &&
122493bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                            (mTimeInjectRequested || mNextNtpTime <= System.currentTimeMillis())) {
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (Config.LOGD) {
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            Log.d(TAG, "Requesting time from NTP server " + mNtpServer);
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
122893bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                        mTimeInjectRequested = false;
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (client.requestTime(mNtpServer, 10000)) {
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            long time = client.getNtpTime();
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            long timeReference = client.getNtpTimeReference();
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            int certainty = (int)(client.getRoundTripTime()/2);
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (Config.LOGD) Log.d(TAG, "calling native_inject_time: " +
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    time + " reference: " + timeReference
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    + " certainty: " + certainty);
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            native_inject_time(time, timeReference, certainty);
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mNextNtpTime = System.currentTimeMillis() + NTP_INTERVAL;
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (Config.LOGD) Log.d(TAG, "requestTime failed");
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mNextNtpTime = System.currentTimeMillis() + RETRY_INTERVAL;
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if ((mXtraDownloadRequested ||
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (mNextXtraTime > 0 && mNextXtraTime <= System.currentTimeMillis()))
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            && xtraDownloader != null) {
124993bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood                        mXtraDownloadRequested = false;
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        byte[] data = xtraDownloader.downloadXtraData();
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (data != null) {
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (Config.LOGD) {
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                Log.d(TAG, "calling native_inject_xtra_data");
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            native_inject_xtra_data(data, data.length);
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mNextXtraTime = 0;
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mNextXtraTime = System.currentTimeMillis() + RETRY_INTERVAL;
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "NetworkThread exiting");
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized void xtraDownloadRequest() {
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mXtraDownloadRequested = true;
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notify();
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
127193bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        synchronized void timeInjectRequest() {
127293bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            mTimeInjectRequested = true;
127393bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood            notify();
127493bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood        }
127593bc44d72125cfe798183b5b6891716dadac0ed7Mike Lockwood
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized void signal() {
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notify();
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized void setDone() {
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Config.LOGD) Log.d(TAG, "stopping NetworkThread");
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDone = true;
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            notify();
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private long getWaitTime() {
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long now = System.currentTimeMillis();
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long waitTime = Long.MAX_VALUE;
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mNtpServer != null) {
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                waitTime = mNextNtpTime - now;
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mNextXtraTime != 0) {
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long xtraWaitTime = mNextXtraTime - now;
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (xtraWaitTime < waitTime) {
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    waitTime = xtraWaitTime;
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (waitTime < 0) {
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                waitTime = 0;
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return waitTime;
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // for GPS SV statistics
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int MAX_SVS = 32;
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int EPHEMERIS_MASK = 0;
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int ALMANAC_MASK = 1;
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int USED_FOR_FIX_MASK = 2;
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // preallocated arrays, to avoid memory allocation in reportStatus()
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvs[] = new int[MAX_SVS];
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSnrs[] = new float[MAX_SVS];
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvElevations[] = new float[MAX_SVS];
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private float mSvAzimuths[] = new float[MAX_SVS];
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvMasks[] = new int[3];
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSvCount;
1318b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    // preallocated to avoid memory allocation in reportNmea()
1319b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    private byte[] mNmeaBuffer = new byte[120];
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static { class_init_native(); }
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native void class_init_native();
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static native boolean native_is_supported();
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_init();
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_disable();
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_cleanup();
1328105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private native boolean native_start(int positionMode, boolean singleFix, int fixInterval);
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_stop();
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_set_fix_frequency(int fixFrequency);
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_delete_aiding_data(int flags);
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_wait_for_event();
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // returns number of SVs
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // mask[0] is ephemeris mask and mask[1] is almanac mask
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native int native_read_sv_status(int[] svs, float[] snrs,
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float[] elevations, float[] azimuths, int[] masks);
1337b16e7800be4f879135f239f1f8f586f3712df01eMike Lockwood    private native int native_read_nmea(int index, byte[] buffer, int bufferSize);
1338d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood    private native void native_inject_location(double latitude, double longitude, float accuracy);
1339d26ce0d903f5141a346d67b2b94437ef3e2880aaMike Lockwood
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // XTRA Support
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_time(long time, long timeReference, int uncertainty);
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native boolean native_supports_xtra();
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native void native_inject_xtra_data(byte[] data, int length);
1344105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1345e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    // AGPS Support
1346e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_open(String apn);
1347e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_closed();
1348e3635c9693c4cd9650684f14e19dcabcea0d488aMike Lockwood    private native void native_agps_data_conn_failed();
1349a9e546169b3c2c9c5f248d2f3abe3b934f48695dMike Lockwood    private native void native_set_agps_server(int type, String hostname, int port);
135022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
135122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    // Network-initiated (NI) Support
135222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private native void native_send_ni_response(int notificationId, int userResponse);
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1354