GpsLocationProvider.java revision ea8a8a6076f04360de2d25b3e5853cde8026cd5f
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"); 569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * you may not use this file except in compliance with the License. 669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * You may obtain a copy of the License at 769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 1269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * See the License for the specific language governing permissions and 1469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server.location; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.app.IAppOpsService; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.app.IBatteryStats; 210795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopianimport com.android.internal.location.GpsNetInitiatedHandler; 220795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopianimport com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification; 230795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopianimport com.android.internal.location.ProviderProperties; 24f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kastenimport com.android.internal.location.ProviderRequest; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.telephony.Phone; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.telephony.PhoneConstants; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.AlarmManager; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.AppOpsManager; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.PendingIntent; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.Cursor; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.hardware.location.GeofenceHardware; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.hardware.location.GeofenceHardwareImpl; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Criteria; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.FusedBatchOptions; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.GpsMeasurementsEvent; 416af763bec7c3f4d50fee8dd0046409bb8a7fe8f6Glenn Kastenimport android.location.IGpsGeofenceHardware; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.IGpsStatusListener; 43957e58670baad8c5995f1368e3b5280f0dbd891fSan Mehatimport android.location.IGpsStatusProvider; 44160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tateimport android.location.ILocationManager; 45a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehatimport android.location.INetInitiatedListener; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Location; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationListener; 48160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tateimport android.location.LocationManager; 49160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tateimport android.location.LocationProvider; 50160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tateimport android.location.LocationRequest; 51160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tateimport android.net.ConnectivityManager; 52160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tateimport android.net.NetworkInfo; 53f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kastenimport android.net.Uri; 54f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kastenimport android.os.AsyncTask; 556793ac943afeb16642f477c43ddfd27e498db37bGlenn Kastenimport android.os.BatteryStats; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Looper; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.UserHandle; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.WorkSource; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Telephony.Carriers; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Telephony.Sms.Intents; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.telephony.SmsMessage; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.telephony.TelephonyManager; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.telephony.gsm.GsmCellLocation; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.NtpTrustedTime; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 766793ac943afeb16642f477c43ddfd27e498db37bGlenn Kastenimport java.io.File; 77e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport java.io.FileDescriptor; 78e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport java.io.FileInputStream; 79e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport java.io.IOException; 80e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport java.io.PrintWriter; 81e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport java.io.StringReader; 82e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport java.net.InetAddress; 83e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport java.net.UnknownHostException; 84e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport java.util.Date; 85e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport java.util.Map.Entry; 86e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport java.util.Properties; 87e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat 88e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat/** 89e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat * A GPS implementation of LocationProvider used by LocationManager. 90e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat * 91e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat * {@hide} 92e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat */ 93e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatpublic class GpsLocationProvider implements LocationProviderInterface { 94e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat 95e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat private static final String TAG = "GpsLocationProvider"; 96e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final ProviderProperties PROPERTIES = new ProviderProperties( 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project true, true, false, false, true, true, true, 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Criteria.POWER_HIGH, Criteria.ACCURACY_FINE); 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // these need to match GpsPositionMode enum in gps.h 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_POSITION_MODE_STANDALONE = 0; 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_POSITION_MODE_MS_BASED = 1; 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_POSITION_MODE_MS_ASSISTED = 2; 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 109887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn // these need to match GpsPositionRecurrence enum in gps.h 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_POSITION_RECURRENCE_PERIODIC = 0; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_POSITION_RECURRENCE_SINGLE = 1; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // these need to match GpsStatusValue defines in gps.h 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_STATUS_NONE = 0; 11569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes private static final int GPS_STATUS_SESSION_BEGIN = 1; 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_STATUS_SESSION_END = 2; 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_STATUS_ENGINE_ON = 3; 11869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes private static final int GPS_STATUS_ENGINE_OFF = 4; 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // these need to match GpsApgsStatusValue defines in gps.h 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** AGPS status event values. */ 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_REQUEST_AGPS_DATA_CONN = 1; 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_RELEASE_AGPS_DATA_CONN = 2; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_AGPS_DATA_CONNECTED = 3; 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_AGPS_DATA_CONN_DONE = 4; 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_AGPS_DATA_CONN_FAILED = 5; 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // these need to match GpsLocationFlags enum in gps.h 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int LOCATION_INVALID = 0; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int LOCATION_HAS_LAT_LONG = 1; 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int LOCATION_HAS_ALTITUDE = 2; 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int LOCATION_HAS_SPEED = 4; 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int LOCATION_HAS_BEARING = 8; 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int LOCATION_HAS_ACCURACY = 16; 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// IMPORTANT - the GPS_DELETE_* symbols here must match constants in gps.h 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_DELETE_EPHEMERIS = 0x0001; 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_DELETE_ALMANAC = 0x0002; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_DELETE_POSITION = 0x0004; 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_DELETE_TIME = 0x0008; 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_DELETE_IONO = 0x0010; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_DELETE_UTC = 0x0020; 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_DELETE_HEALTH = 0x0040; 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_DELETE_SVDIR = 0x0080; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_DELETE_SVSTEER = 0x0100; 14669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes private static final int GPS_DELETE_SADATA = 0x0200; 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_DELETE_RTI = 0x0400; 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_DELETE_CELLDB_INFO = 0x8000; 14969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes private static final int GPS_DELETE_ALL = 0xFFFF; 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The GPS_CAPABILITY_* flags must match the values in gps.h 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_CAPABILITY_SCHEDULING = 0x0000001; 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_CAPABILITY_MSB = 0x0000002; 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_CAPABILITY_MSA = 0x0000004; 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008; 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010; 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // these need to match AGpsType enum in gps.h 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int AGPS_TYPE_SUPL = 1; 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int AGPS_TYPE_C2K = 2; 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // these must match the definitions in gps.h 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int APN_INVALID = 0; 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int APN_IPV4 = 1; 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int APN_IPV6 = 2; 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int APN_IPV4V6 = 3; 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // for mAGpsDataConnectionState 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int AGPS_DATA_CONNECTION_CLOSED = 0; 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int AGPS_DATA_CONNECTION_OPENING = 1; 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int AGPS_DATA_CONNECTION_OPEN = 2; 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Handler messages 174f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten private static final int CHECK_LOCATION = 1; 175e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat private static final int ENABLE = 2; 176f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten private static final int SET_REQUEST = 3; 177f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten private static final int UPDATE_NETWORK_STATE = 4; 178f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten private static final int INJECT_NTP_TIME = 5; 179887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn private static final int DOWNLOAD_XTRA_DATA = 6; 180f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten private static final int UPDATE_LOCATION = 7; 181e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat private static final int ADD_LISTENER = 8; 182e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat private static final int REMOVE_LISTENER = 9; 183e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat private static final int INJECT_NTP_TIME_FINISHED = 10; 18469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes private static final int DOWNLOAD_XTRA_DATA_FINISHED = 11; 1853e458241d9930465a20a861ecb42744355d48e48San Mehat 186f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten // Request setid 1873e458241d9930465a20a861ecb42744355d48e48San Mehat private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1; 1883e458241d9930465a20a861ecb42744355d48e48San Mehat private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2; 1893e458241d9930465a20a861ecb42744355d48e48San Mehat 1903e458241d9930465a20a861ecb42744355d48e48San Mehat // Request ref location 1913e458241d9930465a20a861ecb42744355d48e48San Mehat private static final int AGPS_RIL_REQUEST_REFLOC_CELLID = 1; 192f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten private static final int AGPS_RIL_REQUEST_REFLOC_MAC = 2; 1936793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten 1943e458241d9930465a20a861ecb42744355d48e48San Mehat // ref. location info 1953e458241d9930465a20a861ecb42744355d48e48San Mehat private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1; 1963e458241d9930465a20a861ecb42744355d48e48San Mehat private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2; 197f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten private static final int AGPS_REG_LOCATION_TYPE_MAC = 3; 198f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten 199f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten // set id info 200f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten private static final int AGPS_SETID_TYPE_NONE = 0; 201f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten private static final int AGPS_SETID_TYPE_IMSI = 1; 202f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten private static final int AGPS_SETID_TYPE_MSISDN = 2; 203f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten 204a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat private static final String PROPERTIES_FILE = "/etc/gps.conf"; 205a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat 206a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat private static final int GPS_GEOFENCE_UNAVAILABLE = 1<<0L; 207a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat private static final int GPS_GEOFENCE_AVAILABLE = 1<<1L; 208a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat 209a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat // GPS Geofence errors. Should match gps.h constants. 210a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat private static final int GPS_GEOFENCE_OPERATION_SUCCESS = 0; 211a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat private static final int GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES = 100; 212a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat private static final int GPS_GEOFENCE_ERROR_ID_EXISTS = -101; 213a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat private static final int GPS_GEOFENCE_ERROR_ID_UNKNOWN = -102; 214a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat private static final int GPS_GEOFENCE_ERROR_INVALID_TRANSITION = -103; 215a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat private static final int GPS_GEOFENCE_ERROR_GENERIC = -149; 216a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat 21769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes /** simpler wrapper for ProviderRequest + Worksource */ 218f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten private static class GpsRequest { 2195baa3a62a97544669fba6d65a11c07f252e654ddSteve Block public ProviderRequest request; 220a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat public WorkSource source; 2215baa3a62a97544669fba6d65a11c07f252e654ddSteve Block public GpsRequest(ProviderRequest request, WorkSource source) { 222a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat this.request = request; 223a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat this.source = source; 2243e458241d9930465a20a861ecb42744355d48e48San Mehat } 2253e458241d9930465a20a861ecb42744355d48e48San Mehat } 2261fd0ec738b0a2b97cc28701aa37b1a9869afc684San Mehat 2271fd0ec738b0a2b97cc28701aa37b1a9869afc684San Mehat private Object mLock = new Object(); 2286793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten 2293e458241d9930465a20a861ecb42744355d48e48San Mehat private int mLocationFlags = LOCATION_INVALID; 2303e458241d9930465a20a861ecb42744355d48e48San Mehat 2313e458241d9930465a20a861ecb42744355d48e48San Mehat // current status 2323e458241d9930465a20a861ecb42744355d48e48San Mehat private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE; 2337e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat 2347e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat // time for last status update 2357e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat private long mStatusUpdateTime = SystemClock.elapsedRealtime(); 2363e458241d9930465a20a861ecb42744355d48e48San Mehat 2373e458241d9930465a20a861ecb42744355d48e48San Mehat // turn off GPS fix icon if we haven't received a fix in 10 seconds 2387e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat private static final long RECENT_FIX_TIMEOUT = 10 * 1000; 2397e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat 2407e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat // stop trying if we do not receive a fix within 60 seconds 2413762c311729fe9f3af085c14c5c1fb471d994c03Steve Block private static final int NO_FIX_TIMEOUT = 60 * 1000; 2427e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat 2437e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat // if the fix interval is below this we leave GPS on, 2441fd0ec738b0a2b97cc28701aa37b1a9869afc684San Mehat // if above then we cycle the GPS driver. 24507b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten // Typical hot TTTF is ~5 seconds, so 10 seconds seems sane. 24607b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten private static final int GPS_POLLING_THRESHOLD_INTERVAL = 10 * 1000; 24707b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten 24807b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten // how often to request NTP time, in milliseconds 24907b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten // current setting 24 hours 25007b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten private static final long NTP_INTERVAL = 24*60*60*1000; 25107b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten // how long to wait if we have a network error in NTP or XTRA downloading 25207b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten // current setting - 5 minutes 25307b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten private static final long RETRY_INTERVAL = 5*60*1000; 2547e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat 25507b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten // true if we are enabled, protected by this 256f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten private boolean mEnabled; 257f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten 258f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten // true if we have network connectivity 259f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten private boolean mNetworkAvailable; 2607e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat 26169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes // states for injecting ntp and downloading xtra data 262f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten private static final int STATE_PENDING_NETWORK = 0; 263f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten private static final int STATE_DOWNLOADING = 1; 264f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten private static final int STATE_IDLE = 2; 2650a42b811aea490a9a605b75f0320101f6eafd283San Mehat 266242d65bf9faf1d2bc3468490e510551140e23462San Mehat // flags to trigger NTP or XTRA data download when network becomes available 2673e458241d9930465a20a861ecb42744355d48e48San Mehat // initialized to true so we do NTP and XTRA when the network comes up after booting 2683e458241d9930465a20a861ecb42744355d48e48San Mehat private int mInjectNtpTimePending = STATE_PENDING_NETWORK; 2693e458241d9930465a20a861ecb42744355d48e48San Mehat private int mDownloadXtraDataPending = STATE_PENDING_NETWORK; 2703e458241d9930465a20a861ecb42744355d48e48San Mehat 271160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate // set to true if the GPS engine does not do on-demand NTP time requests 272160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate private boolean mPeriodicTimeInjection; 273160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate 274160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate // true if GPS is navigating 27571f2cf116aab893e224056c38ab146bd1538dd3eSteve Block private boolean mNavigating; 276160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate 277160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate // true if GPS engine is on 278160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate private boolean mEngineOn; 279160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate 280160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate // requested frequency of fixes, in milliseconds 281160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate private int mFixInterval = 1000; 282160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate 283160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate // true if we started navigation 284160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate private boolean mStarted; 285160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate 286160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate // true if single shot request is in progress 287160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate private boolean mSingleShot; 2886793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten 2896793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten // capabilities of the GPS engine 2906793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten private int mEngineCapabilities; 291cc767191cfb675f744e0165608b0a4196aba2b37Glenn Kasten 2926793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten // true if XTRA is supported 2936793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten private boolean mSupportsXtra; 2946793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten 2956793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten // for calculating time to first fix 2966793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten private long mFixRequestTime = 0; 2976793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten // time to first fix for most recent session 298cc767191cfb675f744e0165608b0a4196aba2b37Glenn Kasten private int mTimeToFirstFix = 0; 299cc767191cfb675f744e0165608b0a4196aba2b37Glenn Kasten // time we received our last fix 300cc767191cfb675f744e0165608b0a4196aba2b37Glenn Kasten private long mLastFixTime; 3016793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten 3026793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten private int mPositionMode; 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // properties loaded from PROPERTIES_FILE 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Properties mProperties; 306160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate private String mSuplServerHost; 307160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate private int mSuplServerPort; 308160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate private String mC2KServerHost; 309160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate private int mC2KServerPort; 310160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate 311160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate private final Context mContext; 312160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate private final NtpTrustedTime mNtpTime; 3133762c311729fe9f3af085c14c5c1fb471d994c03Steve Block private final ILocationManager mILocationManager; 314160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate private Location mLocation = new Location(LocationManager.GPS_PROVIDER); 315160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate private Bundle mLocationExtras = new Bundle(); 316160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate private GpsStatusListenerHelper mListenerHelper = new GpsStatusListenerHelper() { 317160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate @Override 318160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate protected boolean isSupported() { 319160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate return native_is_measurement_supported(); 320160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate } 321887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn }; 322887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn 323887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn // Handler for processing events 3246793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten private Handler mHandler; 325887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn 3266793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten private String mAGpsApn; 327887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn private int mApnIpType; 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mAGpsDataConnectionState; 32969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes private InetAddress mAGpsDataConnectionIpAddr; 3306215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block private final ConnectivityManager mConnMgr; 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final GpsNetInitiatedHandler mNIHandler; 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Wakelocks 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static String WAKELOCK_KEY = "GpsLocationProvider"; 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final PowerManager.WakeLock mWakeLock; 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Alarms 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP"; 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT"; 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final AlarmManager mAlarmManager; 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final PendingIntent mWakeupIntent; 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final PendingIntent mTimeoutIntent; 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final IAppOpsService mAppOpsService; 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final IBatteryStats mBatteryStats; 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3476793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten // only modified on handler thread 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private WorkSource mClientSource = new WorkSource(); 3496215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private GeofenceHardwareImpl mGeofenceHardwareImpl; 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() { 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException { 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListenerHelper.addListener(listener); 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35710e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown 35810e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown @Override 35910e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown public void removeGpsStatusListener(IGpsStatusListener listener) { 36010e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown mListenerHelper.removeListener(listener); 36110e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown } 36210e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown }; 36310e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final GpsMeasurementsProvider mGpsMeasurementsProvider = new GpsMeasurementsProvider() { 36510e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown @Override 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isSupported() { 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return native_is_measurement_supported(); 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onFirstListenerAdded() { 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_start_measurement_collection(); 37369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes } 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 37669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes protected void onLastListenerRemoved() { 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_stop_measurement_collection(); 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public IGpsStatusProvider getGpsStatusProvider() { 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mGpsStatusProvider; 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public IGpsGeofenceHardware getGpsGeofenceProxy() { 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mGpsGeofenceBinder; 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public GpsMeasurementsProvider getGpsMeasurementsProvider() { 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mGpsMeasurementsProvider; 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() { 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override public void onReceive(Context context, Intent intent) { 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String action = intent.getAction(); 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (action.equals(ALARM_WAKEUP)) { 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) Log.d(TAG, "ALARM_WAKEUP"); 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startNavigating(false); 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (action.equals(ALARM_TIMEOUT)) { 4016215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT"); 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project hibernate(); 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) { 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkSmsSuplInit(intent); 40559325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) { 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkWapSuplInit(intent); 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 40869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes int networkState; 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false)) { 4108564c8da817a845353d213acd8636b76f567b234Steve Block networkState = LocationProvider.TEMPORARILY_UNAVAILABLE; 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project networkState = LocationProvider.AVAILABLE; 41369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes } 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // retrieve NetworkInfo result for this UID 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NetworkInfo info = 41769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO); 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ConnectivityManager connManager = (ConnectivityManager) 4198564c8da817a845353d213acd8636b76f567b234Steve Block mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project info = connManager.getNetworkInfo(info.getType()); 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateNetworkState(networkState, info); 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4250bca96bcbfe559f9330a01f723c5c9cba51ec05aMarco Nelissen }; 42669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void checkSmsSuplInit(Intent intent) { 42859325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn SmsMessage[] messages = Intents.getMessagesFromIntent(intent); 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i <messages.length; i++) { 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byte[] supl_init = messages[i].getUserData(); 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_agps_ni_message(supl_init,supl_init.length); 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void checkWapSuplInit(Intent intent) { 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byte[] supl_init = (byte[]) intent.getExtra("data"); 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_agps_ni_message(supl_init,supl_init.length); 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean isSupported() { 4410bca96bcbfe559f9330a01f723c5c9cba51ec05aMarco Nelissen return native_is_supported(); 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public GpsLocationProvider(Context context, ILocationManager ilocationManager, 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Looper looper) { 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNtpTime = NtpTrustedTime.getInstance(context); 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mILocationManager = ilocationManager; 44969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes mNIHandler = new GpsNetInitiatedHandler(context); 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLocation.setExtras(mLocationExtras); 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 45359325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn // Create a wake lock 45459325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 45559325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY); 45659325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn mWakeLock.setReferenceCounted(true); 45759325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn 45859325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); 45959325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0); 46059325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0); 46159325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn 46259325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); 46359325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn 46459325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn // App ops service to keep track of who is accessing the GPS 46559325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService( 46659325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn Context.APP_OPS_SERVICE)); 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Battery statistics service to be notified when GPS turns on or off 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService( 4706215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block BatteryStats.SERVICE_NAME)); 47169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mProperties = new Properties(); 47369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes try { 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project File file = new File(PROPERTIES_FILE); 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileInputStream stream = new FileInputStream(file); 47669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes mProperties.load(stream); 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stream.close(); 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSuplServerHost = mProperties.getProperty("SUPL_HOST"); 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String portString = mProperties.getProperty("SUPL_PORT"); 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSuplServerHost != null && portString != null) { 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 48369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes mSuplServerPort = Integer.parseInt(portString); 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException e) { 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "unable to parse SUPL_PORT: " + portString); 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 48969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes mC2KServerHost = mProperties.getProperty("C2K_HOST"); 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project portString = mProperties.getProperty("C2K_PORT"); 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mC2KServerHost != null && portString != null) { 49269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes try { 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mC2KServerPort = Integer.parseInt(portString); 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException e) { 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "unable to parse C2K_PORT: " + portString); 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4976215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block } 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 49969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE); 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // construct handler, listen for events 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler = new ProviderHandler(looper); 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project listenForBroadcasts(); 50569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // also listen for PASSIVE_PROVIDER updates 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.post(new Runnable() { 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 50969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes public void run() { 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LocationManager locManager = 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final long minTime = 0; 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final float minDistance = 0; 51469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes final boolean oneShot = false; 5156215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block LocationRequest request = LocationRequest.createFromDeprecatedProvider( 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LocationManager.PASSIVE_PROVIDER, 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project minTime, 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project minDistance, 51969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes oneShot); 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Don't keep track of this request since it's done on behalf of other clients 52169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes // (which are kept track of separately). 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project request.setHideFromAppOps(true); 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project locManager.requestLocationUpdates( 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project request, 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new NetworkLocationListener(), 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.getLooper()); 52769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes } 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }); 5298564c8da817a845353d213acd8636b76f567b234Steve Block } 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void listenForBroadcasts() { 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IntentFilter intentFilter = new IntentFilter(); 53369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION); 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intentFilter.addDataScheme("sms"); 53569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes intentFilter.addDataAuthority("localhost","7275"); 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.registerReceiver(mBroadcastReciever, intentFilter, null, mHandler); 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intentFilter = new IntentFilter(); 5396215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION); 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intentFilter.addDataType("application/vnd.omaloc-supl-init"); 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IntentFilter.MalformedMimeTypeException e) { 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Malformed SUPL init mime type"); 544add868cebaf62cffe96e79764ea0b7f2320a03ebAmith Yamasani } 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.registerReceiver(mBroadcastReciever, intentFilter, null, mHandler); 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intentFilter = new IntentFilter(); 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intentFilter.addAction(ALARM_WAKEUP); 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intentFilter.addAction(ALARM_TIMEOUT); 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.registerReceiver(mBroadcastReciever, intentFilter, null, mHandler); 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5546215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block /** 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the name of this provider. 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getName() { 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return LocationManager.GPS_PROVIDER; 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ProviderProperties getProperties() { 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return PROPERTIES; 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void updateNetworkState(int state, NetworkInfo info) { 56869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes sendMessage(UPDATE_NETWORK_STATE, state, info); 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5718564c8da817a845353d213acd8636b76f567b234Steve Block private void handleUpdateNetworkState(int state, NetworkInfo info) { 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNetworkAvailable = (state == LocationProvider.AVAILABLE); 57369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 5746215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block if (DEBUG) { 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(TAG, "updateNetworkState " + (mNetworkAvailable ? "available" : "unavailable") 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " info: " + info); 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (info != null) { 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean dataEnabled = Settings.Global.getInt(mContext.getContentResolver(), 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.Global.MOBILE_DATA, 1) == 1; 58269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes boolean networkAvailable = info.isAvailable() && dataEnabled; 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String defaultApn = getSelectedApn(); 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (defaultApn == null) { 58569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes defaultApn = "dummy-apn"; 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_update_network_state(info.isConnected(), info.getType(), 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project info.isRoaming(), networkAvailable, 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project info.getExtraInfo(), defaultApn); 59169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes } 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 59369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) { 59569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes if (mNetworkAvailable) { 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String apnName = info.getExtraInfo(); 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (apnName == null) { 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Assign a dummy value in the case of C2K as otherwise we will have a runtime 59969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes exception in the following call to native_agps_data_conn_open*/ 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project apnName = "dummy-apn"; 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAGpsApn = apnName; 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mApnIpType = getApnIpType(apnName); 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setRouting(); 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) { 60669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes String message = String.format( 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "native_agps_data_conn_open: mAgpsApn=%s, mApnIpType=%s", 60869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes mAGpsApn, mApnIpType); 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(TAG, message); 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_agps_data_conn_open(mAGpsApn, mApnIpType); 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN; 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "call native_agps_data_conn_failed, info: " + info); 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAGpsApn = null; 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mApnIpType = APN_INVALID; 61769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED; 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_agps_data_conn_failed(); 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6206215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block } 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mNetworkAvailable) { 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mInjectNtpTimePending == STATE_PENDING_NETWORK) { 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendMessage(INJECT_NTP_TIME, 0, null); 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) { 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendMessage(DOWNLOAD_XTRA_DATA, 0, null); 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void handleInjectNtpTime() { 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mInjectNtpTimePending == STATE_DOWNLOADING) { 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // already downloading data 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mNetworkAvailable) { 63869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes // try again when network is up 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInjectNtpTimePending = STATE_PENDING_NETWORK; 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 64269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes mInjectNtpTimePending = STATE_DOWNLOADING; 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 64469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes // hold wake lock while task runs 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.acquire(); 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() { 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 64869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes public void run() { 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long delay; 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // force refresh NTP cache when outdated 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mNtpTime.getCacheAge() >= NTP_INTERVAL) { 65369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes mNtpTime.forceRefresh(); 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // only update when NTP time is fresh 65769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes if (mNtpTime.getCacheAge() < NTP_INTERVAL) { 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long time = mNtpTime.getCachedNtpTime(); 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long timeReference = mNtpTime.getCachedNtpTimeReference(); 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long certainty = mNtpTime.getCacheCertainty(); 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = System.currentTimeMillis(); 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(TAG, "NTP server returned: " 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + time + " (" + new Date(time) 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ") reference: " + timeReference 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " certainty: " + certainty 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " system time offset: " + (time - now)); 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_inject_time(time, timeReference, (int) certainty); 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delay = NTP_INTERVAL; 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 672c64edde69d18498fb2954f71a546357b07ab996aEvan Millar if (DEBUG) Log.d(TAG, "requestTime failed"); 67369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes delay = RETRY_INTERVAL; 674c64edde69d18498fb2954f71a546357b07ab996aEvan Millar } 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 67669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes sendMessage(INJECT_NTP_TIME_FINISHED, 0, null); 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mPeriodicTimeInjection) { 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // send delayed message for next NTP injection 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // since this is delayed and not urgent we do not hold a wake lock here 68169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes mHandler.sendEmptyMessageDelayed(INJECT_NTP_TIME, delay); 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // release wake lock held by task 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.release(); 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }); 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void handleDownloadXtraData() { 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDownloadXtraDataPending == STATE_DOWNLOADING) { 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // already downloading data 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mNetworkAvailable) { 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // try again when network is up 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDownloadXtraDataPending = STATE_PENDING_NETWORK; 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDownloadXtraDataPending = STATE_DOWNLOADING; 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 702c64edde69d18498fb2954f71a546357b07ab996aEvan Millar // hold wake lock while task runs 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.acquire(); 70469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() { 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 70669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes public void run() { 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mContext, mProperties); 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project byte[] data = xtraDownloader.downloadXtraData(); 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data != null) { 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) { 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(TAG, "calling native_inject_xtra_data"); 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_inject_xtra_data(data, data.length); 714c64edde69d18498fb2954f71a546357b07ab996aEvan Millar } 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendMessage(DOWNLOAD_XTRA_DATA_FINISHED, 0, null); 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 71869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes if (data == null) { 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // try again later 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // since this is delayed and not urgent we do not hold a wake lock here 721c64edde69d18498fb2954f71a546357b07ab996aEvan Millar mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA, RETRY_INTERVAL); 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // release wake lock held by task 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.release(); 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 727c64edde69d18498fb2954f71a546357b07ab996aEvan Millar }); 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void handleUpdateLocation(Location location) { 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (location.hasAccuracy()) { 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_inject_location(location.getLatitude(), location.getLongitude(), 73369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes location.getAccuracy()); 734c64edde69d18498fb2954f71a546357b07ab996aEvan Millar } 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 737c64edde69d18498fb2954f71a546357b07ab996aEvan Millar /** 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Enables this provider. When enabled, calls to getStatus() 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * must be handled. Hardware may be started up 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * when the provider is enabled. 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 74269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes @Override 7436215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block public void enable() { 74469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes synchronized (mLock) { 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEnabled) return; 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEnabled = true; 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendMessage(ENABLE, 1, null); 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void handleEnable() { 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DEBUG) Log.d(TAG, "handleEnable"); 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean enabled = native_init(); 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (enabled) { 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSupportsXtra = native_supports_xtra(); 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSuplServerHost != null) { 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort); 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mC2KServerHost != null) { 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort); 76469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes } 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mLock) { 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEnabled = false; 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Failed to enable location provider"); 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 77269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Disables this provider. When disabled, calls to getStatus() 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * need not be handled. Hardware may be shut 776c64edde69d18498fb2954f71a546357b07ab996aEvan Millar * down while the provider is disabled. 77769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes */ 778c64edde69d18498fb2954f71a546357b07ab996aEvan Millar @Override 779c64edde69d18498fb2954f71a546357b07ab996aEvan Millar public void disable() { 780c64edde69d18498fb2954f71a546357b07ab996aEvan Millar synchronized (mLock) { 781c64edde69d18498fb2954f71a546357b07ab996aEvan Millar if (!mEnabled) return; 78269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes mEnabled = false; 78369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes } 784c64edde69d18498fb2954f71a546357b07ab996aEvan Millar 78569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes sendMessage(ENABLE, 0, null); 786c64edde69d18498fb2954f71a546357b07ab996aEvan Millar } 78769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 788c64edde69d18498fb2954f71a546357b07ab996aEvan Millar private void handleDisable() { 789c64edde69d18498fb2954f71a546357b07ab996aEvan Millar if (DEBUG) Log.d(TAG, "handleDisable"); 790c64edde69d18498fb2954f71a546357b07ab996aEvan Millar 791c64edde69d18498fb2954f71a546357b07ab996aEvan Millar updateClientUids(new WorkSource()); 792c64edde69d18498fb2954f71a546357b07ab996aEvan Millar stopNavigating(); 793c64edde69d18498fb2954f71a546357b07ab996aEvan Millar mAlarmManager.cancel(mWakeupIntent); 794c64edde69d18498fb2954f71a546357b07ab996aEvan Millar mAlarmManager.cancel(mTimeoutIntent); 795c64edde69d18498fb2954f71a546357b07ab996aEvan Millar 79669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes // do this before releasing wakelock 797c64edde69d18498fb2954f71a546357b07ab996aEvan Millar native_cleanup(); 798c64edde69d18498fb2954f71a546357b07ab996aEvan Millar } 799c64edde69d18498fb2954f71a546357b07ab996aEvan Millar 800c64edde69d18498fb2954f71a546357b07ab996aEvan Millar @Override 801c64edde69d18498fb2954f71a546357b07ab996aEvan Millar public boolean isEnabled() { 802c64edde69d18498fb2954f71a546357b07ab996aEvan Millar synchronized (mLock) { 803c64edde69d18498fb2954f71a546357b07ab996aEvan Millar return mEnabled; 804c64edde69d18498fb2954f71a546357b07ab996aEvan Millar } 805c64edde69d18498fb2954f71a546357b07ab996aEvan Millar } 806c64edde69d18498fb2954f71a546357b07ab996aEvan Millar 80769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes @Override 808c64edde69d18498fb2954f71a546357b07ab996aEvan Millar public int getStatus(Bundle extras) { 8098564c8da817a845353d213acd8636b76f567b234Steve Block if (extras != null) { 810c64edde69d18498fb2954f71a546357b07ab996aEvan Millar extras.putInt("satellites", mSvCount); 811c64edde69d18498fb2954f71a546357b07ab996aEvan Millar } 81269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes return mStatus; 813c64edde69d18498fb2954f71a546357b07ab996aEvan Millar } 814c64edde69d18498fb2954f71a546357b07ab996aEvan Millar 815c64edde69d18498fb2954f71a546357b07ab996aEvan Millar private void updateStatus(int status, int svCount) { 81669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes if (status != mStatus || svCount != mSvCount) { 817c64edde69d18498fb2954f71a546357b07ab996aEvan Millar mStatus = status; 8188564c8da817a845353d213acd8636b76f567b234Steve Block mSvCount = svCount; 819c64edde69d18498fb2954f71a546357b07ab996aEvan Millar mLocationExtras.putInt("satellites", svCount); 820c64edde69d18498fb2954f71a546357b07ab996aEvan Millar mStatusUpdateTime = SystemClock.elapsedRealtime(); 821c64edde69d18498fb2954f71a546357b07ab996aEvan Millar } 82269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes } 82369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 824c64edde69d18498fb2954f71a546357b07ab996aEvan Millar @Override 82569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes public long getStatusUpdateTime() { 826c64edde69d18498fb2954f71a546357b07ab996aEvan Millar return mStatusUpdateTime; 827c64edde69d18498fb2954f71a546357b07ab996aEvan Millar } 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setRequest(ProviderRequest request, WorkSource source) { 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendMessage(SET_REQUEST, 0, new GpsRequest(request, source)); 83269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes } 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void handleSetRequest(ProviderRequest request, WorkSource source) { 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean singleShot = false; 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // see if the request is for a single update 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (request.locationRequests != null && request.locationRequests.size() > 0) { 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // if any request has zero or more than one updates 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // requested, then this is not single-shot mode 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project singleShot = true; 8426215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (LocationRequest lr : request.locationRequests) { 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lr.getNumUpdates() != 1) { 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project singleShot = false; 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 847906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn } 848906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn } 849906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn 850906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn if (DEBUG) Log.d(TAG, "setRequest " + request); 851906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn if (request.reportLocation) { 852906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn // update client uids 853906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn updateClientUids(source); 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFixInterval = (int) request.interval; 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // check for overflow 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFixInterval != request.interval) { 85969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes Log.w(TAG, "interval overflow: " + request.interval); 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFixInterval = Integer.MAX_VALUE; 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 86269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 86369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes // apply request to GPS engine 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) { 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // change period 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC, 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFixInterval, 0, 0)) { 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "set_position_mode failed in setMinTime()"); 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!mStarted) { 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // start GPS 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startNavigating(singleShot); 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateClientUids(new WorkSource()); 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stopNavigating(); 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAlarmManager.cancel(mWakeupIntent); 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAlarmManager.cancel(mTimeoutIntent); 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void updateClientUids(WorkSource source) { 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Update work source. 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project WorkSource[] changes = mClientSource.setReturningDiffs(source); 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (changes == null) { 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project WorkSource newWork = changes[0]; 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project WorkSource goneWork = changes[1]; 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Update sources that were not previously tracked. 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newWork != null) { 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lastuid = -1; 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<newWork.size(); i++) { 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int uid = newWork.get(i); 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService), 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AppOpsManager.OP_GPS, uid, newWork.getName(i)); 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uid != lastuid) { 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lastuid = uid; 9026793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten mBatteryStats.noteStartGps(uid); 903160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate } 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RemoteException e) { 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "RemoteException", e); 906e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat } 9073e458241d9930465a20a861ecb42744355d48e48San Mehat } 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Update sources that are no longer tracked. 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (goneWork != null) { 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lastuid = -1; 913906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn for (int i=0; i<goneWork.size(); i++) { 9140bca96bcbfe559f9330a01f723c5c9cba51ec05aMarco Nelissen try { 91559325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn int uid = goneWork.get(i); 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService), 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AppOpsManager.OP_GPS, uid, goneWork.getName(i)); 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uid != lastuid) { 919c64edde69d18498fb2954f71a546357b07ab996aEvan Millar lastuid = uid; 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBatteryStats.noteStopGps(uid); 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RemoteException e) { 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "RemoteException", e); 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean sendExtraCommand(String command, Bundle extras) { 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identity = Binder.clearCallingIdentity(); 933 boolean result = false; 934 935 if ("delete_aiding_data".equals(command)) { 936 result = deleteAidingData(extras); 937 } else if ("force_time_injection".equals(command)) { 938 sendMessage(INJECT_NTP_TIME, 0, null); 939 result = true; 940 } else if ("force_xtra_injection".equals(command)) { 941 if (mSupportsXtra) { 942 xtraDownloadRequest(); 943 result = true; 944 } 945 } else { 946 Log.w(TAG, "sendExtraCommand: unknown command " + command); 947 } 948 949 Binder.restoreCallingIdentity(identity); 950 return result; 951 } 952 953 private IGpsGeofenceHardware mGpsGeofenceBinder = new IGpsGeofenceHardware.Stub() { 954 public boolean isHardwareGeofenceSupported() { 955 return native_is_geofence_supported(); 956 } 957 958 public boolean addCircularHardwareGeofence(int geofenceId, double latitude, 959 double longitude, double radius, int lastTransition, int monitorTransitions, 960 int notificationResponsiveness, int unknownTimer) { 961 return native_add_geofence(geofenceId, latitude, longitude, radius, 962 lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer); 963 } 964 965 public boolean removeHardwareGeofence(int geofenceId) { 966 return native_remove_geofence(geofenceId); 967 } 968 969 public boolean pauseHardwareGeofence(int geofenceId) { 970 return native_pause_geofence(geofenceId); 971 } 972 973 public boolean resumeHardwareGeofence(int geofenceId, int monitorTransition) { 974 return native_resume_geofence(geofenceId, monitorTransition); 975 } 976 }; 977 978 private boolean deleteAidingData(Bundle extras) { 979 int flags; 980 981 if (extras == null) { 982 flags = GPS_DELETE_ALL; 983 } else { 984 flags = 0; 985 if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS; 986 if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC; 987 if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION; 988 if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME; 989 if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO; 990 if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC; 991 if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH; 992 if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR; 993 if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER; 994 if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA; 995 if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI; 996 if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO; 997 if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL; 998 } 999 1000 if (flags != 0) { 1001 native_delete_aiding_data(flags); 1002 return true; 1003 } 1004 1005 return false; 1006 } 1007 1008 private void startNavigating(boolean singleShot) { 1009 if (!mStarted) { 1010 if (DEBUG) Log.d(TAG, "startNavigating, singleShot is " + singleShot); 1011 mTimeToFirstFix = 0; 1012 mLastFixTime = 0; 1013 mStarted = true; 1014 mSingleShot = singleShot; 1015 mPositionMode = GPS_POSITION_MODE_STANDALONE; 1016 1017 if (Settings.Global.getInt(mContext.getContentResolver(), 1018 Settings.Global.ASSISTED_GPS_ENABLED, 1) != 0) { 1019 if (singleShot && hasCapability(GPS_CAPABILITY_MSA)) { 1020 mPositionMode = GPS_POSITION_MODE_MS_ASSISTED; 1021 } else if (hasCapability(GPS_CAPABILITY_MSB)) { 1022 mPositionMode = GPS_POSITION_MODE_MS_BASED; 1023 } 1024 } 1025 1026 if (DEBUG) { 1027 String mode; 1028 1029 switch(mPositionMode) { 1030 case GPS_POSITION_MODE_STANDALONE: 1031 mode = "standalone"; 1032 break; 1033 case GPS_POSITION_MODE_MS_ASSISTED: 1034 mode = "MS_ASSISTED"; 1035 break; 1036 case GPS_POSITION_MODE_MS_BASED: 1037 mode = "MS_BASED"; 1038 break; 1039 default: 1040 mode = "unknown"; 1041 break; 1042 } 1043 Log.d(TAG, "setting position_mode to " + mode); 1044 } 1045 1046 int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000); 1047 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC, 1048 interval, 0, 0)) { 1049 mStarted = false; 1050 Log.e(TAG, "set_position_mode failed in startNavigating()"); 1051 return; 1052 } 1053 if (!native_start()) { 1054 mStarted = false; 1055 Log.e(TAG, "native_start failed in startNavigating()"); 1056 return; 1057 } 1058 1059 // reset SV count to zero 1060 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0); 1061 mFixRequestTime = System.currentTimeMillis(); 1062 if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) { 1063 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT 1064 // and our fix interval is not short 1065 if (mFixInterval >= NO_FIX_TIMEOUT) { 1066 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1067 SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent); 1068 } 1069 } 1070 } 1071 } 1072 1073 private void stopNavigating() { 1074 if (DEBUG) Log.d(TAG, "stopNavigating"); 1075 if (mStarted) { 1076 mStarted = false; 1077 mSingleShot = false; 1078 native_stop(); 1079 mTimeToFirstFix = 0; 1080 mLastFixTime = 0; 1081 mLocationFlags = LOCATION_INVALID; 1082 1083 // reset SV count to zero 1084 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0); 1085 } 1086 } 1087 1088 private void hibernate() { 1089 // stop GPS until our next fix interval arrives 1090 stopNavigating(); 1091 mAlarmManager.cancel(mTimeoutIntent); 1092 mAlarmManager.cancel(mWakeupIntent); 1093 long now = SystemClock.elapsedRealtime(); 1094 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, mWakeupIntent); 1095 } 1096 1097 private boolean hasCapability(int capability) { 1098 return ((mEngineCapabilities & capability) != 0); 1099 } 1100 1101 1102 /** 1103 * called from native code to update our position. 1104 */ 1105 private void reportLocation(int flags, double latitude, double longitude, double altitude, 1106 float speed, float bearing, float accuracy, long timestamp) { 1107 if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude + 1108 " timestamp: " + timestamp); 1109 1110 synchronized (mLocation) { 1111 mLocationFlags = flags; 1112 if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) { 1113 mLocation.setLatitude(latitude); 1114 mLocation.setLongitude(longitude); 1115 mLocation.setTime(timestamp); 1116 // It would be nice to push the elapsed real-time timestamp 1117 // further down the stack, but this is still useful 1118 mLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos()); 1119 } 1120 if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) { 1121 mLocation.setAltitude(altitude); 1122 } else { 1123 mLocation.removeAltitude(); 1124 } 1125 if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) { 1126 mLocation.setSpeed(speed); 1127 } else { 1128 mLocation.removeSpeed(); 1129 } 1130 if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) { 1131 mLocation.setBearing(bearing); 1132 } else { 1133 mLocation.removeBearing(); 1134 } 1135 if ((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) { 1136 mLocation.setAccuracy(accuracy); 1137 } else { 1138 mLocation.removeAccuracy(); 1139 } 1140 mLocation.setExtras(mLocationExtras); 1141 1142 try { 1143 mILocationManager.reportLocation(mLocation, false); 1144 } catch (RemoteException e) { 1145 Log.e(TAG, "RemoteException calling reportLocation"); 1146 } 1147 } 1148 1149 mLastFixTime = System.currentTimeMillis(); 1150 // report time to first fix 1151 if (mTimeToFirstFix == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) { 1152 mTimeToFirstFix = (int)(mLastFixTime - mFixRequestTime); 1153 if (DEBUG) Log.d(TAG, "TTFF: " + mTimeToFirstFix); 1154 1155 // notify status listeners 1156 mListenerHelper.onFirstFix(mTimeToFirstFix); 1157 } 1158 1159 if (mSingleShot) { 1160 stopNavigating(); 1161 } 1162 1163 if (mStarted && mStatus != LocationProvider.AVAILABLE) { 1164 // we want to time out if we do not receive a fix 1165 // within the time out and we are requesting infrequent fixes 1166 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) { 1167 mAlarmManager.cancel(mTimeoutIntent); 1168 } 1169 1170 // send an intent to notify that the GPS is receiving fixes. 1171 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION); 1172 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true); 1173 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 1174 updateStatus(LocationProvider.AVAILABLE, mSvCount); 1175 } 1176 1177 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted && 1178 mFixInterval > GPS_POLLING_THRESHOLD_INTERVAL) { 1179 if (DEBUG) Log.d(TAG, "got fix, hibernating"); 1180 hibernate(); 1181 } 1182 } 1183 1184 /** 1185 * called from native code to update our status 1186 */ 1187 private void reportStatus(int status) { 1188 if (DEBUG) Log.v(TAG, "reportStatus status: " + status); 1189 1190 boolean wasNavigating = mNavigating; 1191 switch (status) { 1192 case GPS_STATUS_SESSION_BEGIN: 1193 mNavigating = true; 1194 mEngineOn = true; 1195 break; 1196 case GPS_STATUS_SESSION_END: 1197 mNavigating = false; 1198 break; 1199 case GPS_STATUS_ENGINE_ON: 1200 mEngineOn = true; 1201 break; 1202 case GPS_STATUS_ENGINE_OFF: 1203 mEngineOn = false; 1204 mNavigating = false; 1205 break; 1206 } 1207 1208 if (wasNavigating != mNavigating) { 1209 mListenerHelper.onStatusChanged(mNavigating); 1210 1211 // send an intent to notify that the GPS has been enabled or disabled 1212 Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION); 1213 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating); 1214 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 1215 } 1216 } 1217 1218 /** 1219 * called from native code to update SV info 1220 */ 1221 private void reportSvStatus() { 1222 int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks); 1223 mListenerHelper.onSvStatusChanged( 1224 svCount, 1225 mSvs, 1226 mSnrs, 1227 mSvElevations, 1228 mSvAzimuths, 1229 mSvMasks[EPHEMERIS_MASK], 1230 mSvMasks[ALMANAC_MASK], 1231 mSvMasks[USED_FOR_FIX_MASK]); 1232 1233 if (VERBOSE) { 1234 Log.v(TAG, "SV count: " + svCount + 1235 " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) + 1236 " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK])); 1237 for (int i = 0; i < svCount; i++) { 1238 Log.v(TAG, "sv: " + mSvs[i] + 1239 " snr: " + mSnrs[i]/10 + 1240 " elev: " + mSvElevations[i] + 1241 " azimuth: " + mSvAzimuths[i] + 1242 ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? " " : " E") + 1243 ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? " " : " A") + 1244 ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U")); 1245 } 1246 } 1247 1248 // return number of sets used in fix instead of total 1249 updateStatus(mStatus, Integer.bitCount(mSvMasks[USED_FOR_FIX_MASK])); 1250 1251 if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 && 1252 System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) { 1253 // send an intent to notify that the GPS is no longer receiving fixes. 1254 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION); 1255 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false); 1256 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 1257 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount); 1258 } 1259 } 1260 1261 /** 1262 * called from native code to update AGPS status 1263 */ 1264 private void reportAGpsStatus(int type, int status, byte[] ipaddr) { 1265 switch (status) { 1266 case GPS_REQUEST_AGPS_DATA_CONN: 1267 if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN"); 1268 // Set mAGpsDataConnectionState before calling startUsingNetworkFeature 1269 // to avoid a race condition with handleUpdateNetworkState() 1270 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING; 1271 int result = mConnMgr.startUsingNetworkFeature( 1272 ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL); 1273 if (ipaddr != null) { 1274 try { 1275 mAGpsDataConnectionIpAddr = InetAddress.getByAddress(ipaddr); 1276 } catch (UnknownHostException e) { 1277 Log.e(TAG, "Bad IP Address: " + ipaddr, e); 1278 mAGpsDataConnectionIpAddr = null; 1279 } 1280 } 1281 1282 if (result == PhoneConstants.APN_ALREADY_ACTIVE) { 1283 if (DEBUG) Log.d(TAG, "PhoneConstants.APN_ALREADY_ACTIVE"); 1284 if (mAGpsApn != null) { 1285 setRouting(); 1286 native_agps_data_conn_open(mAGpsApn, mApnIpType); 1287 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN; 1288 } else { 1289 Log.e(TAG, "mAGpsApn not set when receiving PhoneConstants.APN_ALREADY_ACTIVE"); 1290 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED; 1291 native_agps_data_conn_failed(); 1292 } 1293 } else if (result == PhoneConstants.APN_REQUEST_STARTED) { 1294 if (DEBUG) Log.d(TAG, "PhoneConstants.APN_REQUEST_STARTED"); 1295 // Nothing to do here 1296 } else { 1297 if (DEBUG) Log.d(TAG, "startUsingNetworkFeature failed, value is " + 1298 result); 1299 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED; 1300 native_agps_data_conn_failed(); 1301 } 1302 break; 1303 case GPS_RELEASE_AGPS_DATA_CONN: 1304 if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN"); 1305 if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) { 1306 mConnMgr.stopUsingNetworkFeature( 1307 ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL); 1308 native_agps_data_conn_closed(); 1309 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED; 1310 mAGpsDataConnectionIpAddr = null; 1311 } 1312 break; 1313 case GPS_AGPS_DATA_CONNECTED: 1314 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED"); 1315 break; 1316 case GPS_AGPS_DATA_CONN_DONE: 1317 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE"); 1318 break; 1319 case GPS_AGPS_DATA_CONN_FAILED: 1320 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED"); 1321 break; 1322 } 1323 } 1324 1325 /** 1326 * called from native code to report NMEA data received 1327 */ 1328 private void reportNmea(long timestamp) { 1329 int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length); 1330 String nmea = new String(mNmeaBuffer, 0 /* offset */, length); 1331 mListenerHelper.onNmeaReceived(timestamp, nmea); 1332 } 1333 1334 /** 1335 * called from native code - Gps Data callback 1336 */ 1337 private void reportMeasurementData(GpsMeasurementsEvent event) { 1338 mGpsMeasurementsProvider.onMeasurementsAvailable(event); 1339 } 1340 1341 /** 1342 * called from native code to inform us what the GPS engine capabilities are 1343 */ 1344 private void setEngineCapabilities(int capabilities) { 1345 mEngineCapabilities = capabilities; 1346 1347 if (!hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME) && !mPeriodicTimeInjection) { 1348 mPeriodicTimeInjection = true; 1349 requestUtcTime(); 1350 } 1351 } 1352 1353 /** 1354 * called from native code to request XTRA data 1355 */ 1356 private void xtraDownloadRequest() { 1357 if (DEBUG) Log.d(TAG, "xtraDownloadRequest"); 1358 sendMessage(DOWNLOAD_XTRA_DATA, 0, null); 1359 } 1360 1361 /** 1362 * Helper method to construct a location object. 1363 */ 1364 private Location buildLocation( 1365 int flags, 1366 double latitude, 1367 double longitude, 1368 double altitude, 1369 float speed, 1370 float bearing, 1371 float accuracy, 1372 long timestamp) { 1373 Location location = new Location(LocationManager.GPS_PROVIDER); 1374 if((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) { 1375 location.setLatitude(latitude); 1376 location.setLongitude(longitude); 1377 location.setTime(timestamp); 1378 location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos()); 1379 } 1380 if((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) { 1381 location.setAltitude(altitude); 1382 } 1383 if((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) { 1384 location.setSpeed(speed); 1385 } 1386 if((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) { 1387 location.setBearing(bearing); 1388 } 1389 if((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) { 1390 location.setAccuracy(accuracy); 1391 } 1392 return location; 1393 } 1394 1395 /** 1396 * Converts the GPS HAL status to the internal Geofence Hardware status. 1397 */ 1398 private int getGeofenceStatus(int status) { 1399 switch(status) { 1400 case GPS_GEOFENCE_OPERATION_SUCCESS: 1401 return GeofenceHardware.GEOFENCE_SUCCESS; 1402 case GPS_GEOFENCE_ERROR_GENERIC: 1403 return GeofenceHardware.GEOFENCE_FAILURE; 1404 case GPS_GEOFENCE_ERROR_ID_EXISTS: 1405 return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS; 1406 case GPS_GEOFENCE_ERROR_INVALID_TRANSITION: 1407 return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION; 1408 case GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES: 1409 return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES; 1410 case GPS_GEOFENCE_ERROR_ID_UNKNOWN: 1411 return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN; 1412 default: 1413 return -1; 1414 } 1415 } 1416 1417 /** 1418 * Called from native to report GPS Geofence transition 1419 * All geofence callbacks are called on the same thread 1420 */ 1421 private void reportGeofenceTransition(int geofenceId, int flags, double latitude, 1422 double longitude, double altitude, float speed, float bearing, float accuracy, 1423 long timestamp, int transition, long transitionTimestamp) { 1424 if (mGeofenceHardwareImpl == null) { 1425 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 1426 } 1427 Location location = buildLocation( 1428 flags, 1429 latitude, 1430 longitude, 1431 altitude, 1432 speed, 1433 bearing, 1434 accuracy, 1435 timestamp); 1436 mGeofenceHardwareImpl.reportGeofenceTransition( 1437 geofenceId, 1438 location, 1439 transition, 1440 transitionTimestamp, 1441 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE, 1442 FusedBatchOptions.SourceTechnologies.GNSS); 1443 } 1444 1445 /** 1446 * called from native code to report GPS status change. 1447 */ 1448 private void reportGeofenceStatus(int status, int flags, double latitude, 1449 double longitude, double altitude, float speed, float bearing, float accuracy, 1450 long timestamp) { 1451 if (mGeofenceHardwareImpl == null) { 1452 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 1453 } 1454 Location location = buildLocation( 1455 flags, 1456 latitude, 1457 longitude, 1458 altitude, 1459 speed, 1460 bearing, 1461 accuracy, 1462 timestamp); 1463 int monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE; 1464 if(status == GPS_GEOFENCE_AVAILABLE) { 1465 monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE; 1466 } 1467 mGeofenceHardwareImpl.reportGeofenceMonitorStatus( 1468 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE, 1469 monitorStatus, 1470 location, 1471 FusedBatchOptions.SourceTechnologies.GNSS); 1472 } 1473 1474 /** 1475 * called from native code - Geofence Add callback 1476 */ 1477 private void reportGeofenceAddStatus(int geofenceId, int status) { 1478 if (mGeofenceHardwareImpl == null) { 1479 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 1480 } 1481 mGeofenceHardwareImpl.reportGeofenceAddStatus(geofenceId, getGeofenceStatus(status)); 1482 } 1483 1484 /** 1485 * called from native code - Geofence Remove callback 1486 */ 1487 private void reportGeofenceRemoveStatus(int geofenceId, int status) { 1488 if (mGeofenceHardwareImpl == null) { 1489 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 1490 } 1491 mGeofenceHardwareImpl.reportGeofenceRemoveStatus(geofenceId, getGeofenceStatus(status)); 1492 } 1493 1494 /** 1495 * called from native code - Geofence Pause callback 1496 */ 1497 private void reportGeofencePauseStatus(int geofenceId, int status) { 1498 if (mGeofenceHardwareImpl == null) { 1499 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 1500 } 1501 mGeofenceHardwareImpl.reportGeofencePauseStatus(geofenceId, getGeofenceStatus(status)); 1502 } 1503 1504 /** 1505 * called from native code - Geofence Resume callback 1506 */ 1507 private void reportGeofenceResumeStatus(int geofenceId, int status) { 1508 if (mGeofenceHardwareImpl == null) { 1509 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 1510 } 1511 mGeofenceHardwareImpl.reportGeofenceResumeStatus(geofenceId, getGeofenceStatus(status)); 1512 } 1513 1514 //============================================================= 1515 // NI Client support 1516 //============================================================= 1517 private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() { 1518 // Sends a response for an NI reqeust to HAL. 1519 @Override 1520 public boolean sendNiResponse(int notificationId, int userResponse) 1521 { 1522 // TODO Add Permission check 1523 1524 if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId + 1525 ", response: " + userResponse); 1526 native_send_ni_response(notificationId, userResponse); 1527 return true; 1528 } 1529 }; 1530 1531 public INetInitiatedListener getNetInitiatedListener() { 1532 return mNetInitiatedListener; 1533 } 1534 1535 // Called by JNI function to report an NI request. 1536 public void reportNiNotification( 1537 int notificationId, 1538 int niType, 1539 int notifyFlags, 1540 int timeout, 1541 int defaultResponse, 1542 String requestorId, 1543 String text, 1544 int requestorIdEncoding, 1545 int textEncoding, 1546 String extras // Encoded extra data 1547 ) 1548 { 1549 Log.i(TAG, "reportNiNotification: entered"); 1550 Log.i(TAG, "notificationId: " + notificationId + 1551 ", niType: " + niType + 1552 ", notifyFlags: " + notifyFlags + 1553 ", timeout: " + timeout + 1554 ", defaultResponse: " + defaultResponse); 1555 1556 Log.i(TAG, "requestorId: " + requestorId + 1557 ", text: " + text + 1558 ", requestorIdEncoding: " + requestorIdEncoding + 1559 ", textEncoding: " + textEncoding); 1560 1561 GpsNiNotification notification = new GpsNiNotification(); 1562 1563 notification.notificationId = notificationId; 1564 notification.niType = niType; 1565 notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0; 1566 notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0; 1567 notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0; 1568 notification.timeout = timeout; 1569 notification.defaultResponse = defaultResponse; 1570 notification.requestorId = requestorId; 1571 notification.text = text; 1572 notification.requestorIdEncoding = requestorIdEncoding; 1573 notification.textEncoding = textEncoding; 1574 1575 // Process extras, assuming the format is 1576 // one of more lines of "key = value" 1577 Bundle bundle = new Bundle(); 1578 1579 if (extras == null) extras = ""; 1580 Properties extraProp = new Properties(); 1581 1582 try { 1583 extraProp.load(new StringReader(extras)); 1584 } 1585 catch (IOException e) 1586 { 1587 Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras); 1588 } 1589 1590 for (Entry<Object, Object> ent : extraProp.entrySet()) 1591 { 1592 bundle.putString((String) ent.getKey(), (String) ent.getValue()); 1593 } 1594 1595 notification.extras = bundle; 1596 1597 mNIHandler.handleNiNotification(notification); 1598 } 1599 1600 /** 1601 * Called from native code to request set id info. 1602 * We should be careful about receiving null string from the TelephonyManager, 1603 * because sending null String to JNI function would cause a crash. 1604 */ 1605 1606 private void requestSetID(int flags) { 1607 TelephonyManager phone = (TelephonyManager) 1608 mContext.getSystemService(Context.TELEPHONY_SERVICE); 1609 int type = AGPS_SETID_TYPE_NONE; 1610 String data = ""; 1611 1612 if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) { 1613 String data_temp = phone.getSubscriberId(); 1614 if (data_temp == null) { 1615 // This means the framework does not have the SIM card ready. 1616 } else { 1617 // This means the framework has the SIM card. 1618 data = data_temp; 1619 type = AGPS_SETID_TYPE_IMSI; 1620 } 1621 } 1622 else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) { 1623 String data_temp = phone.getLine1Number(); 1624 if (data_temp == null) { 1625 // This means the framework does not have the SIM card ready. 1626 } else { 1627 // This means the framework has the SIM card. 1628 data = data_temp; 1629 type = AGPS_SETID_TYPE_MSISDN; 1630 } 1631 } 1632 native_agps_set_id(type, data); 1633 } 1634 1635 /** 1636 * Called from native code to request utc time info 1637 */ 1638 1639 private void requestUtcTime() { 1640 sendMessage(INJECT_NTP_TIME, 0, null); 1641 } 1642 1643 /** 1644 * Called from native code to request reference location info 1645 */ 1646 1647 private void requestRefLocation(int flags) { 1648 TelephonyManager phone = (TelephonyManager) 1649 mContext.getSystemService(Context.TELEPHONY_SERVICE); 1650 final int phoneType = phone.getPhoneType(); 1651 if (phoneType == TelephonyManager.PHONE_TYPE_GSM) { 1652 GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation(); 1653 if ((gsm_cell != null) && (phone.getNetworkOperator() != null) 1654 && (phone.getNetworkOperator().length() > 3)) { 1655 int type; 1656 int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0,3)); 1657 int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3)); 1658 int networkType = phone.getNetworkType(); 1659 if (networkType == TelephonyManager.NETWORK_TYPE_UMTS 1660 || networkType == TelephonyManager.NETWORK_TYPE_HSDPA 1661 || networkType == TelephonyManager.NETWORK_TYPE_HSUPA 1662 || networkType == TelephonyManager.NETWORK_TYPE_HSPA 1663 || networkType == TelephonyManager.NETWORK_TYPE_HSPAP) { 1664 type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID; 1665 } else { 1666 type = AGPS_REF_LOCATION_TYPE_GSM_CELLID; 1667 } 1668 native_agps_set_ref_location_cellid(type, mcc, mnc, 1669 gsm_cell.getLac(), gsm_cell.getCid()); 1670 } else { 1671 Log.e(TAG,"Error getting cell location info."); 1672 } 1673 } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) { 1674 Log.e(TAG, "CDMA not supported."); 1675 } 1676 } 1677 1678 private void sendMessage(int message, int arg, Object obj) { 1679 // hold a wake lock until this message is delivered 1680 // note that this assumes the message will not be removed from the queue before 1681 // it is handled (otherwise the wake lock would be leaked). 1682 mWakeLock.acquire(); 1683 mHandler.obtainMessage(message, arg, 1, obj).sendToTarget(); 1684 } 1685 1686 private final class ProviderHandler extends Handler { 1687 public ProviderHandler(Looper looper) { 1688 super(looper, null, true /*async*/); 1689 } 1690 1691 @Override 1692 public void handleMessage(Message msg) { 1693 int message = msg.what; 1694 switch (message) { 1695 case ENABLE: 1696 if (msg.arg1 == 1) { 1697 handleEnable(); 1698 } else { 1699 handleDisable(); 1700 } 1701 break; 1702 case SET_REQUEST: 1703 GpsRequest gpsRequest = (GpsRequest) msg.obj; 1704 handleSetRequest(gpsRequest.request, gpsRequest.source); 1705 break; 1706 case UPDATE_NETWORK_STATE: 1707 handleUpdateNetworkState(msg.arg1, (NetworkInfo)msg.obj); 1708 break; 1709 case INJECT_NTP_TIME: 1710 handleInjectNtpTime(); 1711 break; 1712 case DOWNLOAD_XTRA_DATA: 1713 if (mSupportsXtra) { 1714 handleDownloadXtraData(); 1715 } 1716 break; 1717 case INJECT_NTP_TIME_FINISHED: 1718 mInjectNtpTimePending = STATE_IDLE; 1719 break; 1720 case DOWNLOAD_XTRA_DATA_FINISHED: 1721 mDownloadXtraDataPending = STATE_IDLE; 1722 break; 1723 case UPDATE_LOCATION: 1724 handleUpdateLocation((Location)msg.obj); 1725 break; 1726 } 1727 if (msg.arg2 == 1) { 1728 // wakelock was taken for this message, release it 1729 mWakeLock.release(); 1730 } 1731 } 1732 }; 1733 1734 private final class NetworkLocationListener implements LocationListener { 1735 @Override 1736 public void onLocationChanged(Location location) { 1737 // this callback happens on mHandler looper 1738 if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) { 1739 handleUpdateLocation(location); 1740 } 1741 } 1742 @Override 1743 public void onStatusChanged(String provider, int status, Bundle extras) { } 1744 @Override 1745 public void onProviderEnabled(String provider) { } 1746 @Override 1747 public void onProviderDisabled(String provider) { } 1748 } 1749 1750 private String getSelectedApn() { 1751 Uri uri = Uri.parse("content://telephony/carriers/preferapn"); 1752 Cursor cursor = null; 1753 try { 1754 cursor = mContext.getContentResolver().query( 1755 uri, 1756 new String[] { "apn" }, 1757 null /* selection */, 1758 null /* selectionArgs */, 1759 Carriers.DEFAULT_SORT_ORDER); 1760 if (cursor != null && cursor.moveToFirst()) { 1761 return cursor.getString(0); 1762 } else { 1763 Log.e(TAG, "No APN found to select."); 1764 } 1765 } catch (Exception e) { 1766 Log.e(TAG, "Error encountered on selecting the APN.", e); 1767 } finally { 1768 if (cursor != null) { 1769 cursor.close(); 1770 } 1771 } 1772 1773 return null; 1774 } 1775 1776 private int getApnIpType(String apn) { 1777 if (apn == null) { 1778 return APN_INVALID; 1779 } 1780 1781 // look for cached data to use 1782 if (apn.equals(mAGpsApn) && mApnIpType != APN_INVALID) { 1783 return mApnIpType; 1784 } 1785 1786 String selection = String.format("current = 1 and apn = '%s' and carrier_enabled = 1", apn); 1787 Cursor cursor = null; 1788 try { 1789 cursor = mContext.getContentResolver().query( 1790 Carriers.CONTENT_URI, 1791 new String[] { Carriers.PROTOCOL }, 1792 selection, 1793 null, 1794 Carriers.DEFAULT_SORT_ORDER); 1795 1796 if (null != cursor && cursor.moveToFirst()) { 1797 return translateToApnIpType(cursor.getString(0), apn); 1798 } else { 1799 Log.e(TAG, "No entry found in query for APN: " + apn); 1800 } 1801 } catch (Exception e) { 1802 Log.e(TAG, "Error encountered on APN query for: " + apn, e); 1803 } finally { 1804 if (cursor != null) { 1805 cursor.close(); 1806 } 1807 } 1808 1809 return APN_INVALID; 1810 } 1811 1812 private int translateToApnIpType(String ipProtocol, String apn) { 1813 if ("IP".equals(ipProtocol)) { 1814 return APN_IPV4; 1815 } 1816 if ("IPV6".equals(ipProtocol)) { 1817 return APN_IPV6; 1818 } 1819 if ("IPV4V6".equals(ipProtocol)) { 1820 return APN_IPV4V6; 1821 } 1822 1823 // we hit the default case so the ipProtocol is not recognized 1824 String message = String.format("Unknown IP Protocol: %s, for APN: %s", ipProtocol, apn); 1825 Log.e(TAG, message); 1826 return APN_INVALID; 1827 } 1828 1829 private void setRouting() { 1830 if (mAGpsDataConnectionIpAddr == null) { 1831 return; 1832 } 1833 1834 boolean result = mConnMgr.requestRouteToHostAddress( 1835 ConnectivityManager.TYPE_MOBILE_SUPL, 1836 mAGpsDataConnectionIpAddr); 1837 1838 if (!result) { 1839 Log.e(TAG, "Error requesting route to host: " + mAGpsDataConnectionIpAddr); 1840 } else if (DEBUG) { 1841 Log.d(TAG, "Successfully requested route to host: " + mAGpsDataConnectionIpAddr); 1842 } 1843 } 1844 1845 @Override 1846 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1847 StringBuilder s = new StringBuilder(); 1848 s.append(" mFixInterval=").append(mFixInterval).append("\n"); 1849 s.append(" mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities)).append(" ("); 1850 if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHED "); 1851 if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB "); 1852 if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA "); 1853 if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT "); 1854 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME "); 1855 s.append(")\n"); 1856 1857 s.append(native_get_internal_state()); 1858 pw.append(s); 1859 } 1860 1861 // for GPS SV statistics 1862 private static final int MAX_SVS = 32; 1863 private static final int EPHEMERIS_MASK = 0; 1864 private static final int ALMANAC_MASK = 1; 1865 private static final int USED_FOR_FIX_MASK = 2; 1866 1867 // preallocated arrays, to avoid memory allocation in reportStatus() 1868 private int mSvs[] = new int[MAX_SVS]; 1869 private float mSnrs[] = new float[MAX_SVS]; 1870 private float mSvElevations[] = new float[MAX_SVS]; 1871 private float mSvAzimuths[] = new float[MAX_SVS]; 1872 private int mSvMasks[] = new int[3]; 1873 private int mSvCount; 1874 // preallocated to avoid memory allocation in reportNmea() 1875 private byte[] mNmeaBuffer = new byte[120]; 1876 1877 static { class_init_native(); } 1878 private static native void class_init_native(); 1879 private static native boolean native_is_supported(); 1880 1881 private native boolean native_init(); 1882 private native void native_cleanup(); 1883 private native boolean native_set_position_mode(int mode, int recurrence, int min_interval, 1884 int preferred_accuracy, int preferred_time); 1885 private native boolean native_start(); 1886 private native boolean native_stop(); 1887 private native void native_delete_aiding_data(int flags); 1888 // returns number of SVs 1889 // mask[0] is ephemeris mask and mask[1] is almanac mask 1890 private native int native_read_sv_status(int[] svs, float[] snrs, 1891 float[] elevations, float[] azimuths, int[] masks); 1892 private native int native_read_nmea(byte[] buffer, int bufferSize); 1893 private native void native_inject_location(double latitude, double longitude, float accuracy); 1894 1895 // XTRA Support 1896 private native void native_inject_time(long time, long timeReference, int uncertainty); 1897 private native boolean native_supports_xtra(); 1898 private native void native_inject_xtra_data(byte[] data, int length); 1899 1900 // DEBUG Support 1901 private native String native_get_internal_state(); 1902 1903 // AGPS Support 1904 private native void native_agps_data_conn_open(String apn, int apnIpType); 1905 private native void native_agps_data_conn_closed(); 1906 private native void native_agps_data_conn_failed(); 1907 private native void native_agps_ni_message(byte [] msg, int length); 1908 private native void native_set_agps_server(int type, String hostname, int port); 1909 1910 // Network-initiated (NI) Support 1911 private native void native_send_ni_response(int notificationId, int userResponse); 1912 1913 // AGPS ril suport 1914 private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc, 1915 int lac, int cid); 1916 private native void native_agps_set_id(int type, String setid); 1917 1918 private native void native_update_network_state(boolean connected, int type, 1919 boolean roaming, boolean available, String extraInfo, String defaultAPN); 1920 1921 // Hardware Geofence support. 1922 private static native boolean native_is_geofence_supported(); 1923 private static native boolean native_add_geofence(int geofenceId, double latitude, 1924 double longitude, double radius, int lastTransition,int monitorTransitions, 1925 int notificationResponsivenes, int unknownTimer); 1926 private static native boolean native_remove_geofence(int geofenceId); 1927 private static native boolean native_resume_geofence(int geofenceId, int transitions); 1928 private static native boolean native_pause_geofence(int geofenceId); 1929 1930 // Gps Hal measurements support. 1931 private static native boolean native_is_measurement_supported(); 1932 private static native boolean native_start_measurement_collection(); 1933 private static native boolean native_stop_measurement_collection(); 1934} 1935