LocationManagerService.java revision fff2fda0199dedbf1079454dca98a81190dce765
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.BufferedReader; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileReader; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileWriter; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashSet; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map; 319637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwoodimport java.util.Observable; 329637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwoodimport java.util.Observer; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.regex.Pattern; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.PendingIntent; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver; 389637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwoodimport android.content.ContentQueryMap; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager; 449637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwoodimport android.database.Cursor; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Address; 46a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwoodimport android.location.IGeocodeProvider; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.IGpsStatusListener; 4815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwoodimport android.location.IGpsStatusProvider; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.ILocationListener; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.ILocationManager; 51e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwoodimport android.location.ILocationProvider; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Location; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationManager; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationProvider; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.ConnectivityManager; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 613d12b51ee38537f6760a833618948f936e75561dMike Lockwoodimport android.os.Looper; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager; 64e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwoodimport android.os.Process; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.PrintWriterPrinter; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.location.GpsLocationProvider; 72e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwoodimport com.android.internal.location.LocationProviderProxy; 737ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwoodimport com.android.internal.location.MockProvider; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The service class that manages LocationProviders and issues location 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * updates and alerts. 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide} 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 813d12b51ee38537f6760a833618948f936e75561dMike Lockwoodpublic class LocationManagerService extends ILocationManager.Stub implements Runnable { 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "LocationManagerService"; 83105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project private static final boolean LOCAL_LOGV = false; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Minimum time interval between last known location writes, in milliseconds. 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long MIN_LAST_KNOWN_LOCATION_TIME = 60L * 1000L; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Max time to hold wake lock for, in milliseconds. 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long MAX_TIME_FOR_WAKE_LOCK = 60 * 1000L; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The last time a location was written, by provider name. 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private HashMap<String,Long> mLastWriteTime = new HashMap<String,Long>(); 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final Pattern PATTERN_COMMA = Pattern.compile(","); 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String ACCESS_FINE_LOCATION = 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.ACCESS_FINE_LOCATION; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String ACCESS_COARSE_LOCATION = 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.ACCESS_COARSE_LOCATION; 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String ACCESS_MOCK_LOCATION = 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.ACCESS_MOCK_LOCATION; 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String ACCESS_LOCATION_EXTRA_COMMANDS = 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS; 104275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood private static final String INSTALL_LOCATION_PROVIDER = 105275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood android.Manifest.permission.INSTALL_LOCATION_PROVIDER; 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set of providers that are explicitly enabled 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Set<String> mEnabledProviders = new HashSet<String>(); 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set of providers that are explicitly disabled 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Set<String> mDisabledProviders = new HashSet<String>(); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Locations, status values, and extras for mock providers 1147ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood private final HashMap<String,MockProvider> mMockProviders = new HashMap<String,MockProvider>(); 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static boolean sProvidersLoaded = false; 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Context mContext; 119a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood private IGeocodeProvider mGeocodeProvider; 12015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood private IGpsStatusProvider mGpsStatusProvider; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private LocationWorkerHandler mLocationHandler; 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Handler messages 1244e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood private static final int MESSAGE_LOCATION_CHANGED = 1; 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1260528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood // wakelock variables 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static String WAKELOCK_KEY = "LocationManagerService"; 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private PowerManager.WakeLock mWakeLock = null; 12948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood private int mPendingBroadcasts; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1322f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood * List of all receivers. 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1342f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood private final HashMap<Object, Receiver> mReceivers = new HashMap<Object, Receiver>(); 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood 13715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood /** 13815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood * List of location providers. 13915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood */ 14015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood private final ArrayList<LocationProviderProxy> mProviders = 14115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood new ArrayList<LocationProviderProxy>(); 14215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood private final HashMap<String, LocationProviderProxy> mProvidersByName 14315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood = new HashMap<String, LocationProviderProxy>(); 14415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1462f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood * Object used internally for synchronization 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1482f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood private final Object mLock = new Object(); 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Mapping from provider name to all its UpdateRecords 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final HashMap<String,ArrayList<UpdateRecord>> mRecordsByProvider = 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new HashMap<String,ArrayList<UpdateRecord>>(); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Proximity listeners 15748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood private Receiver mProximityReceiver = null; 15848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood private ILocationListener mProximityListener = null; 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private HashMap<PendingIntent,ProximityAlert> mProximityAlerts = 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new HashMap<PendingIntent,ProximityAlert>(); 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private HashSet<ProximityAlert> mProximitiesEntered = 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new HashSet<ProximityAlert>(); 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Last known location for each provider 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private HashMap<String,Location> mLastKnownLocation = 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new HashMap<String,Location>(); 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1684df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project private int mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE; 1694df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project 1709637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood // for Settings change notification 1719637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood private ContentQueryMap mSettings; 1729637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A wrapper class holding either an ILocationListener or a PendingIntent to receive 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * location updates. 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 17748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished { 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ILocationListener mListener; 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final PendingIntent mPendingIntent; 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Object mKey; 1812f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>(); 18248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood int mPendingBroadcasts; 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1842f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood Receiver(ILocationListener listener) { 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListener = listener; 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPendingIntent = null; 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mKey = listener.asBinder(); 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1902f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood Receiver(PendingIntent intent) { 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPendingIntent = intent; 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListener = null; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mKey = intent; 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean equals(Object otherObj) { 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (otherObj instanceof Receiver) { 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mKey.equals( 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ((Receiver)otherObj).mKey); 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int hashCode() { 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mKey.hashCode(); 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2093681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mListener != null) { 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "Receiver{" 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + Integer.toHexString(System.identityHashCode(this)) 2152f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood + " Listener " + mKey + "}"; 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "Receiver{" 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + Integer.toHexString(System.identityHashCode(this)) 2192f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood + " Intent " + mKey + "}"; 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isListener() { 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mListener != null; 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isPendingIntent() { 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mPendingIntent != null; 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ILocationListener getListener() { 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mListener != null) { 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mListener; 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException("Request for non-existent listener"); 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public PendingIntent getPendingIntent() { 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mPendingIntent != null) { 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mPendingIntent; 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException("Request for non-existent intent"); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean callStatusChangedLocked(String provider, int status, Bundle extras) { 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mListener != null) { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 24848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood synchronized (this) { 24948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // synchronize to ensure incrementPendingBroadcastsLocked() 25048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // is called before decrementPendingBroadcasts() 25148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood mListener.onStatusChanged(provider, status, extras); 25248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood if (mListener != mProximityListener) { 25348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // call this after broadcasting so we do not increment 25448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // if we throw an exeption. 25548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood incrementPendingBroadcastsLocked(); 25648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 25748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RemoteException e) { 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent statusChanged = new Intent(); 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project statusChanged.putExtras(extras); 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status); 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 26648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood synchronized (this) { 26748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // synchronize to ensure incrementPendingBroadcastsLocked() 26848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // is called before decrementPendingBroadcasts() 26948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler); 27048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // call this after broadcasting so we do not increment 27148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // if we throw an exeption. 27248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood incrementPendingBroadcastsLocked(); 27348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (PendingIntent.CanceledException e) { 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean callLocationChangedLocked(Location location) { 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mListener != null) { 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 28448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood synchronized (this) { 28548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // synchronize to ensure incrementPendingBroadcastsLocked() 28648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // is called before decrementPendingBroadcasts() 28748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood mListener.onLocationChanged(location); 28848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood if (mListener != mProximityListener) { 28948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // call this after broadcasting so we do not increment 29048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // if we throw an exeption. 29148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood incrementPendingBroadcastsLocked(); 29248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 29348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RemoteException e) { 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent locationChanged = new Intent(); 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, location); 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 30148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood synchronized (this) { 30248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // synchronize to ensure incrementPendingBroadcastsLocked() 30348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // is called before decrementPendingBroadcasts() 30448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler); 30548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // call this after broadcasting so we do not increment 30648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // if we throw an exeption. 30748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood incrementPendingBroadcastsLocked(); 30848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 30948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } catch (PendingIntent.CanceledException e) { 31048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood return false; 31148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 31248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 31348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood return true; 31448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 31548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood 31648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood public boolean callProviderEnabledLocked(String provider, boolean enabled) { 31748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood if (mListener != null) { 31848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood try { 31948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood synchronized (this) { 32048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // synchronize to ensure incrementPendingBroadcastsLocked() 32148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // is called before decrementPendingBroadcasts() 32248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood if (enabled) { 32348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood mListener.onProviderEnabled(provider); 32448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } else { 32548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood mListener.onProviderDisabled(provider); 32648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 32748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood if (mListener != mProximityListener) { 32848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // call this after broadcasting so we do not increment 32948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // if we throw an exeption. 33048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood incrementPendingBroadcastsLocked(); 33148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 33248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 33348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } catch (RemoteException e) { 33448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood return false; 33548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 33648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } else { 33748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood Intent providerIntent = new Intent(); 33848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled); 33948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood try { 34048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood synchronized (this) { 34148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // synchronize to ensure incrementPendingBroadcastsLocked() 34248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // is called before decrementPendingBroadcasts() 34348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler); 34448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // call this after broadcasting so we do not increment 34548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // if we throw an exeption. 34648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood incrementPendingBroadcastsLocked(); 34748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (PendingIntent.CanceledException e) { 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void binderDied() { 356105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (LOCAL_LOGV) { 357105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Log.v(TAG, "Location listener died"); 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3592f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeUpdatesLocked(this); 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood synchronized (this) { 36348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood if (mPendingBroadcasts > 0) { 36448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood LocationManagerService.this.decrementPendingBroadcasts(); 36548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood mPendingBroadcasts = 0; 36648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 36748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 36848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 36948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood 37048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood public void onSendFinished(PendingIntent pendingIntent, Intent intent, 37148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood int resultCode, String resultData, Bundle resultExtras) { 3720528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood synchronized (this) { 3730528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood decrementPendingBroadcastsLocked(); 3740528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood } 37548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 37648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood 3770528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood // this must be called while synchronized by caller in a synchronized block 37848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // containing the sending of the broadcaset 37948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood private void incrementPendingBroadcastsLocked() { 38048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood if (mPendingBroadcasts++ == 0) { 3810528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood LocationManagerService.this.incrementPendingBroadcasts(); 38248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 38348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 38448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood 3850528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood private void decrementPendingBroadcastsLocked() { 3860528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood if (--mPendingBroadcasts == 0) { 3870528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood LocationManagerService.this.decrementPendingBroadcasts(); 38848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 38948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 39048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 39148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood 39248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood public void locationCallbackFinished(ILocationListener listener) { 39348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood Receiver receiver = getReceiver(listener); 39448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood if (receiver != null) { 3950528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood synchronized (receiver) { 3960528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood // so wakelock calls will succeed 3970528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood long identity = Binder.clearCallingIdentity(); 3980528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood receiver.decrementPendingBroadcastsLocked(); 3990528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood Binder.restoreCallingIdentity(identity); 4000528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood } 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4049637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood private final class SettingsObserver implements Observer { 4059637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood public void update(Observable o, Object arg) { 4062f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 4079637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood updateProvidersLocked(); 4089637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood } 4099637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood } 4109637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood } 4119637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Location readLastKnownLocationLocked(String provider) { 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Location location = null; 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String s = null; 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project File f = new File(LocationManager.SYSTEM_DIR + "/location." 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + provider); 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!f.exists()) { 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BufferedReader reader = new BufferedReader(new FileReader(f), 256); 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project s = reader.readLine(); 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Unable to read last known location", e); 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (s == null) { 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] tokens = PATTERN_COMMA.split(s); 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int idx = 0; 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long time = Long.parseLong(tokens[idx++]); 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double latitude = Double.parseDouble(tokens[idx++]); 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double longitude = Double.parseDouble(tokens[idx++]); 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double altitude = Double.parseDouble(tokens[idx++]); 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float bearing = Float.parseFloat(tokens[idx++]); 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float speed = Float.parseFloat(tokens[idx++]); 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project location = new Location(provider); 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project location.setTime(time); 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project location.setLatitude(latitude); 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project location.setLongitude(longitude); 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project location.setAltitude(altitude); 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project location.setBearing(bearing); 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project location.setSpeed(speed); 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException nfe) { 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "NumberFormatException reading last known location", nfe); 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return location; 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void writeLastKnownLocationLocked(String provider, 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Location location) { 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = SystemClock.elapsedRealtime(); 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Long last = mLastWriteTime.get(provider); 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((last != null) 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (now - last.longValue() < MIN_LAST_KNOWN_LOCATION_TIME)) { 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLastWriteTime.put(provider, now); 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(100); 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(location.getTime()); 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(','); 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(location.getLatitude()); 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(','); 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(location.getLongitude()); 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(','); 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(location.getAltitude()); 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(','); 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(location.getBearing()); 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(','); 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(location.getSpeed()); 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FileWriter writer = null; 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project File d = new File(LocationManager.SYSTEM_DIR); 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!d.exists()) { 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!d.mkdirs()) { 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Unable to create directory to write location"); 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project File f = new File(LocationManager.SYSTEM_DIR + "/location." + provider); 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project writer = new FileWriter(f); 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project writer.write(sb.toString()); 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Unable to write location", e); 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (writer != null) { 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project writer.close(); 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Exception closing file", e); 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 50315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood private void addProvider(LocationProviderProxy provider) { 50415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood mProviders.add(provider); 50515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood mProvidersByName.put(provider.getName(), provider); 50615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood } 50715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood 50815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood private void removeProvider(LocationProviderProxy provider) { 50915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood mProviders.remove(provider); 510fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu provider.unlinkProvider(); 51115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood mProvidersByName.remove(provider.getName()); 51215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood } 51315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void loadProviders() { 5152f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sProvidersLoaded) { 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Load providers 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project loadProvidersLocked(); 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sProvidersLoaded = true; 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void loadProvidersLocked() { 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project _loadProvidersLocked(); 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Exception loading providers:", e); 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void _loadProvidersLocked() { 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Attempt to load "real" providers first 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (GpsLocationProvider.isSupported()) { 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Create a gps location provider 53815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood GpsLocationProvider provider = new GpsLocationProvider(mContext, this); 53915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood mGpsStatusProvider = provider.getGpsStatusProvider(); 5408dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood LocationProviderProxy proxy = new LocationProviderProxy(LocationManager.GPS_PROVIDER, provider); 5418dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood addProvider(proxy); 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateProvidersLocked(); 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context the context that the LocationManagerService runs in 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public LocationManagerService(Context context) { 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(); 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 5533d12b51ee38537f6760a833618948f936e75561dMike Lockwood 5543d12b51ee38537f6760a833618948f936e75561dMike Lockwood Thread thread = new Thread(null, this, "LocationManagerService"); 5553d12b51ee38537f6760a833618948f936e75561dMike Lockwood thread.start(); 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 557105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (LOCAL_LOGV) { 558105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Log.v(TAG, "Constructed LocationManager Service"); 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5603d12b51ee38537f6760a833618948f936e75561dMike Lockwood } 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5623d12b51ee38537f6760a833618948f936e75561dMike Lockwood private void initialize() { 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Create a wake lock, needs to be done before calling loadProviders() below 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY); 5660528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Load providers 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project loadProviders(); 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Register for Network (Wifi or Mobile) updates 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IntentFilter intentFilter = new IntentFilter(); 5720528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 5730528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood // Register for Package Manager updates 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED); 5760528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood mContext.registerReceiver(mBroadcastReceiver, intentFilter); 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5789637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood // listen for settings changes 5799637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood ContentResolver resolver = mContext.getContentResolver(); 5809637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood Cursor settingsCursor = resolver.query(Settings.Secure.CONTENT_URI, null, 5819637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood "(" + Settings.System.NAME + "=?)", 5829637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED}, 5839637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood null); 5849637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mLocationHandler); 5859637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood SettingsObserver settingsObserver = new SettingsObserver(); 5869637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood mSettings.addObserver(settingsObserver); 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5893d12b51ee38537f6760a833618948f936e75561dMike Lockwood public void run() 5903d12b51ee38537f6760a833618948f936e75561dMike Lockwood { 5913d12b51ee38537f6760a833618948f936e75561dMike Lockwood Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 5923d12b51ee38537f6760a833618948f936e75561dMike Lockwood Looper.prepare(); 5933d12b51ee38537f6760a833618948f936e75561dMike Lockwood mLocationHandler = new LocationWorkerHandler(); 5943d12b51ee38537f6760a833618948f936e75561dMike Lockwood initialize(); 5953d12b51ee38537f6760a833618948f936e75561dMike Lockwood Looper.loop(); 5963d12b51ee38537f6760a833618948f936e75561dMike Lockwood } 5973d12b51ee38537f6760a833618948f936e75561dMike Lockwood 598275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood public void installLocationProvider(String name, ILocationProvider provider) { 599275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER) 600275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood != PackageManager.PERMISSION_GRANTED) { 601275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission"); 602e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwood } 603e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwood 6042f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 6053681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood // check to see if we are reinstalling a dead provider 6063681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood LocationProviderProxy oldProvider = mProvidersByName.get(name); 6073681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood if (oldProvider != null) { 6083681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood if (oldProvider.isDead()) { 6093681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood Log.d(TAG, "replacing dead provider"); 6103681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood removeProvider(oldProvider); 6113681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood } else { 6123681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood throw new IllegalArgumentException("Provider \"" + name + "\" already exists"); 6133681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood } 6143681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood } 6153681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood 6168dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood LocationProviderProxy proxy = new LocationProviderProxy(name, provider); 6178dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood addProvider(proxy); 6188dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood updateProvidersLocked(); 619275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood 6208dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood // notify provider of current network state 6218dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood proxy.updateNetworkState(mNetworkState); 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 625275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood public void installGeocodeProvider(IGeocodeProvider provider) { 626275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER) 627275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood != PackageManager.PERMISSION_GRANTED) { 628275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission"); 629a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood } 630a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood 631a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood mGeocodeProvider = provider; 632a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood } 633a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean isAllowedBySettingsLocked(String provider) { 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEnabledProviders.contains(provider)) { 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDisabledProviders.contains(provider)) { 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Use system settings 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentResolver resolver = mContext.getContentResolver(); 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String allowedProviders = Settings.Secure.getString(resolver, 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.Secure.LOCATION_PROVIDERS_ALLOWED); 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ((allowedProviders != null) && (allowedProviders.contains(provider))); 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void checkPermissionsSafe(String provider) { 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LocationManager.GPS_PROVIDER.equals(provider) 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (mContext.checkCallingPermission(ACCESS_FINE_LOCATION) 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED)) { 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires ACCESS_FINE_LOCATION permission"); 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LocationManager.NETWORK_PROVIDER.equals(provider) 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (mContext.checkCallingPermission(ACCESS_FINE_LOCATION) 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED) 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (mContext.checkCallingPermission(ACCESS_COARSE_LOCATION) 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED)) { 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException( 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Requires ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission"); 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean isAllowedProviderSafe(String provider) { 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LocationManager.GPS_PROVIDER.equals(provider) 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (mContext.checkCallingPermission(ACCESS_FINE_LOCATION) 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED)) { 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LocationManager.NETWORK_PROVIDER.equals(provider) 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (mContext.checkCallingPermission(ACCESS_FINE_LOCATION) 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED) 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (mContext.checkCallingPermission(ACCESS_COARSE_LOCATION) 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED)) { 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public List<String> getAllProviders() { 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6842f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return _getAllProvidersLocked(); 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SecurityException se) { 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw se; 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "getAllProviders got exception:", e); 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private List<String> _getAllProvidersLocked() { 696105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (LOCAL_LOGV) { 697105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Log.v(TAG, "getAllProviders"); 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 69915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood ArrayList<String> out = new ArrayList<String>(mProviders.size()); 70015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood for (int i = mProviders.size() - 1; i >= 0; i--) { 70115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood LocationProviderProxy p = mProviders.get(i); 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.add(p.getName()); 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return out; 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public List<String> getProviders(boolean enabledOnly) { 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 7092f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return _getProvidersLocked(enabledOnly); 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SecurityException se) { 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw se; 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 715105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Log.e(TAG, "getProviders got exception:", e); 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private List<String> _getProvidersLocked(boolean enabledOnly) { 721105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (LOCAL_LOGV) { 722105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Log.v(TAG, "getProviders"); 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 72415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood ArrayList<String> out = new ArrayList<String>(mProviders.size()); 72515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood for (int i = mProviders.size() - 1; i >= 0; i--) { 72615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood LocationProviderProxy p = mProviders.get(i); 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String name = p.getName(); 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isAllowedProviderSafe(name)) { 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (enabledOnly && !isAllowedBySettingsLocked(name)) { 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.add(name); 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return out; 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void updateProvidersLocked() { 73915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood for (int i = mProviders.size() - 1; i >= 0; i--) { 74015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood LocationProviderProxy p = mProviders.get(i); 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean isEnabled = p.isEnabled(); 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String name = p.getName(); 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean shouldBeEnabled = isAllowedBySettingsLocked(name); 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isEnabled && !shouldBeEnabled) { 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateProviderListenersLocked(name, false); 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!isEnabled && shouldBeEnabled) { 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateProviderListenersLocked(name, true); 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void updateProviderListenersLocked(String provider, boolean enabled) { 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int listeners = 0; 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 75715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood LocationProviderProxy p = mProvidersByName.get(provider); 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (p == null) { 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Receiver> deadReceivers = null; 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (records != null) { 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int N = records.size(); 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<N; i++) { 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project UpdateRecord record = records.get(i); 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Sends a notification message to the receiver 77048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) { 77148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood if (deadReceivers == null) { 77248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood deadReceivers = new ArrayList<Receiver>(); 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7744686657cee6411eb00235d49b4a8663a96361a00Simon Schoar deadReceivers.add(record.mReceiver); 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project listeners++; 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (deadReceivers != null) { 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=deadReceivers.size()-1; i>=0; i--) { 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeUpdatesLocked(deadReceivers.get(i)); 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (enabled) { 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project p.enable(); 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (listeners > 0) { 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project p.setMinTime(getMinTimeLocked(provider)); 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project p.enableLocationTracking(true); 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project p.enableLocationTracking(false); 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project p.disable(); 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private long getMinTimeLocked(String provider) { 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long minTime = Long.MAX_VALUE; 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (records != null) { 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=records.size()-1; i>=0; i--) { 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project minTime = Math.min(minTime, records.get(i).mMinTime); 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return minTime; 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class UpdateRecord { 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final String mProvider; 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Receiver mReceiver; 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final long mMinTime; 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final float mMinDistance; 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int mUid; 8152f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood Location mLastFixBroadcast; 8162f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood long mLastStatusBroadcast; 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note: must be constructed with lock held. 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project UpdateRecord(String provider, long minTime, float minDistance, 8222f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood Receiver receiver, int uid) { 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mProvider = provider; 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mReceiver = receiver; 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMinTime = minTime; 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMinDistance = minDistance; 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUid = uid; 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (records == null) { 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project records = new ArrayList<UpdateRecord>(); 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRecordsByProvider.put(provider, records); 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!records.contains(this)) { 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project records.add(this); 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Method to be called when a record will no longer be used. Calling this multiple times 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * must have the same effect as calling it once. 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void disposeLocked() { 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<UpdateRecord> records = mRecordsByProvider.get(this.mProvider); 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project records.remove(this); 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "UpdateRecord{" 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + Integer.toHexString(System.identityHashCode(this)) 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " " + mProvider + " " + mReceiver + "}"; 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void dump(PrintWriter pw, String prefix) { 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(prefix + this); 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(prefix + "mProvider=" + mProvider + " mReceiver=" + mReceiver); 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(prefix + "mMinTime=" + mMinTime + " mMinDistance=" + mMinDistance); 8592f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood pw.println(prefix + "mUid=" + mUid); 8602f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood pw.println(prefix + "mLastFixBroadcast:"); 8612f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood mLastFixBroadcast.dump(new PrintWriterPrinter(pw), prefix + " "); 8622f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood pw.println(prefix + "mLastStatusBroadcast=" + mLastStatusBroadcast); 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Calls dispose(). 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override protected void finalize() { 8692f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project disposeLocked(); 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8752f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood private Receiver getReceiver(ILocationListener listener) { 8762f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood IBinder binder = listener.asBinder(); 8772f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood Receiver receiver = mReceivers.get(binder); 8782f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood if (receiver == null) { 8792f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood receiver = new Receiver(listener); 8802f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood mReceivers.put(binder, receiver); 8812f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood 8822f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood try { 8832f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood if (receiver.isListener()) { 8842f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood receiver.getListener().asBinder().linkToDeath(receiver, 0); 8852f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood } 8862f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood } catch (RemoteException e) { 8872f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood Log.e(TAG, "linkToDeath failed:", e); 8882f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood return null; 8892f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood } 8902f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood } 8912f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood return receiver; 8922f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood } 8932f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood 8942f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood private Receiver getReceiver(PendingIntent intent) { 8952f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood Receiver receiver = mReceivers.get(intent); 8962f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood if (receiver == null) { 8972f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood receiver = new Receiver(intent); 8982f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood mReceivers.put(intent, receiver); 8992f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood } 9002f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood return receiver; 9012f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood } 9022f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood 9032f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood private boolean providerHasListener(String provider, int uid, Receiver excludedReceiver) { 9042f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 9052f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood if (records != null) { 9062f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood for (int i = records.size() - 1; i >= 0; i--) { 9072f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood UpdateRecord record = records.get(i); 9082f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood if (record.mUid == uid && record.mReceiver != excludedReceiver) { 9092f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood return true; 9102f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood } 9112f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood } 9122f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood } 91395427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood for (ProximityAlert alert : mProximityAlerts.values()) { 91495427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood if (alert.mUid == uid) { 91595427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood return true; 9162f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood } 9172f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood } 9182f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood return false; 9192f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood } 9202f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void requestLocationUpdates(String provider, 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long minTime, float minDistance, ILocationListener listener) { 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9252f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 9262f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood requestLocationUpdatesLocked(provider, minTime, minDistance, getReceiver(listener)); 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SecurityException se) { 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw se; 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "requestUpdates got exception:", e); 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void requestLocationUpdatesPI(String provider, 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long minTime, float minDistance, PendingIntent intent) { 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9382f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 9392f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood requestLocationUpdatesLocked(provider, minTime, minDistance, getReceiver(intent)); 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SecurityException se) { 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw se; 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "requestUpdates got exception:", e); 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void requestLocationUpdatesLocked(String provider, 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long minTime, float minDistance, Receiver receiver) { 950105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (LOCAL_LOGV) { 951105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Log.v(TAG, "_requestLocationUpdates: listener = " + receiver); 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 95415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood LocationProviderProxy proxy = mProvidersByName.get(provider); 95515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood if (proxy == null) { 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("provider=" + provider); 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkPermissionsSafe(provider); 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // so wakelock calls will succeed 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int callingUid = Binder.getCallingUid(); 9632f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood boolean newUid = !providerHasListener(provider, callingUid, null); 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identity = Binder.clearCallingIdentity(); 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9662f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood UpdateRecord r = new UpdateRecord(provider, minTime, minDistance, receiver, callingUid); 9672f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood UpdateRecord oldRecord = receiver.mUpdateRecords.put(provider, r); 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (oldRecord != null) { 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oldRecord.disposeLocked(); 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9722f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood if (newUid) { 97315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood proxy.addListener(callingUid); 9742f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood } 9752f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean isProviderEnabled = isAllowedBySettingsLocked(provider); 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isProviderEnabled) { 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long minTimeForProvider = getMinTimeLocked(provider); 97915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood proxy.setMinTime(minTimeForProvider); 98015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood proxy.enableLocationTracking(true); 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 98248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // Notify the listener that updates are currently disabled 98348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood receiver.callProviderEnabledLocked(provider, false); 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.restoreCallingIdentity(identity); 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeUpdates(ILocationListener listener) { 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9922f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 9932f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood removeUpdatesLocked(getReceiver(listener)); 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SecurityException se) { 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw se; 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "removeUpdates got exception:", e); 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeUpdatesPI(PendingIntent intent) { 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 10042f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 10052f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood removeUpdatesLocked(getReceiver(intent)); 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SecurityException se) { 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw se; 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "removeUpdates got exception:", e); 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void removeUpdatesLocked(Receiver receiver) { 1015105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (LOCAL_LOGV) { 1016105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Log.v(TAG, "_removeUpdates: listener = " + receiver); 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // so wakelock calls will succeed 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int callingUid = Binder.getCallingUid(); 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identity = Binder.clearCallingIdentity(); 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 10232f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) { 10242f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood receiver.getListener().asBinder().unlinkToDeath(receiver, 0); 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Record which providers were associated with this listener 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HashSet<String> providers = new HashSet<String>(); 10292f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood HashMap<String,UpdateRecord> oldRecords = receiver.mUpdateRecords; 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (oldRecords != null) { 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Call dispose() on the obsolete update records. 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (UpdateRecord record : oldRecords.values()) { 10332f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood if (!providerHasListener(record.mProvider, callingUid, receiver)) { 103415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood LocationProviderProxy proxy = mProvidersByName.get(record.mProvider); 103515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood if (proxy != null) { 103615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood proxy.removeListener(callingUid); 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project record.disposeLocked(); 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Accumulate providers 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project providers.addAll(oldRecords.keySet()); 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // See if the providers associated with this listener have any 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // other listeners; if one does, inform it of the new smallest minTime 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // value; if one does not, disable location tracking for it 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String provider : providers) { 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If provider is already disabled, don't need to do anything 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isAllowedBySettingsLocked(provider)) { 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean hasOtherListener = false; 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<UpdateRecord> recordsForProvider = mRecordsByProvider.get(provider); 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (recordsForProvider != null && recordsForProvider.size() > 0) { 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project hasOtherListener = true; 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 106015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood LocationProviderProxy p = mProvidersByName.get(provider); 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (p != null) { 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (hasOtherListener) { 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project p.setMinTime(getMinTimeLocked(provider)); 10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project p.enableLocationTracking(false); 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.restoreCallingIdentity(identity); 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean addGpsStatusListener(IGpsStatusListener listener) { 107515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood if (mGpsStatusProvider == null) { 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingPermission(ACCESS_FINE_LOCATION) != 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PackageManager.PERMISSION_GRANTED) { 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires ACCESS_FINE_LOCATION permission"); 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 108415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood mGpsStatusProvider.addGpsStatusListener(listener); 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (RemoteException e) { 108615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood Log.e(TAG, "mGpsStatusProvider.addGpsStatusListener failed", e); 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeGpsStatusListener(IGpsStatusListener listener) { 10932f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 109415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood try { 109515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood mGpsStatusProvider.removeGpsStatusListener(listener); 109615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood } catch (Exception e) { 109715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood Log.e(TAG, "mGpsStatusProvider.removeGpsStatusListener failed", e); 109815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood } 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean sendExtraCommand(String provider, String command, Bundle extras) { 11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // first check for permission to the provider 11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkPermissionsSafe(provider); 11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // and check for ACCESS_LOCATION_EXTRA_COMMANDS 11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mContext.checkCallingPermission(ACCESS_LOCATION_EXTRA_COMMANDS) 11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED)) { 11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission"); 11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11112f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 111215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood LocationProviderProxy proxy = mProvidersByName.get(provider); 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (provider == null) { 11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 111715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood return proxy.sendExtraCommand(command, extras); 11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class ProximityAlert { 11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int mUid; 11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final double mLatitude; 11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final double mLongitude; 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final float mRadius; 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final long mExpiration; 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final PendingIntent mIntent; 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Location mLocation; 11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ProximityAlert(int uid, double latitude, double longitude, 11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float radius, long expiration, PendingIntent intent) { 11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUid = uid; 11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLatitude = latitude; 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLongitude = longitude; 11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRadius = radius; 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mExpiration = expiration; 11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIntent = intent; 11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLocation = new Location(""); 11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLocation.setLatitude(latitude); 11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLocation.setLongitude(longitude); 11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long getExpiration() { 11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mExpiration; 11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PendingIntent getIntent() { 11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mIntent; 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean isInProximity(double latitude, double longitude) { 11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Location loc = new Location(""); 11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project loc.setLatitude(latitude); 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project loc.setLongitude(longitude); 11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double radius = loc.distanceTo(mLocation); 11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return radius <= mRadius; 11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "ProximityAlert{" 11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + Integer.toHexString(System.identityHashCode(this)) 11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " uid " + mUid + mIntent + "}"; 11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void dump(PrintWriter pw, String prefix) { 11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(prefix + this); 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(prefix + "mLatitude=" + mLatitude + " mLongitude=" + mLongitude); 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(prefix + "mRadius=" + mRadius + " mExpiration=" + mExpiration); 11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(prefix + "mIntent=" + mIntent); 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(prefix + "mLocation:"); 11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLocation.dump(new PrintWriterPrinter(pw), prefix + " "); 11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Listener for receiving locations to trigger proximity alerts 117948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood class ProximityListener extends ILocationListener.Stub implements PendingIntent.OnFinished { 11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean isGpsAvailable = false; 11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Note: this is called with the lock held. 11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onLocationChanged(Location loc) { 11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If Gps is available, then ignore updates from NetworkLocationProvider 11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (loc.getProvider().equals(LocationManager.GPS_PROVIDER)) { 11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project isGpsAvailable = true; 11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isGpsAvailable && loc.getProvider().equals(LocationManager.NETWORK_PROVIDER)) { 11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Process proximity alerts 11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long now = System.currentTimeMillis(); 11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double latitude = loc.getLatitude(); 11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double longitude = loc.getLongitude(); 11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<PendingIntent> intentsToRemove = null; 11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (ProximityAlert alert : mProximityAlerts.values()) { 12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PendingIntent intent = alert.getIntent(); 12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long expiration = alert.getExpiration(); 12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((expiration == -1) || (now <= expiration)) { 12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean entered = mProximitiesEntered.contains(alert); 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean inProximity = 12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project alert.isInProximity(latitude, longitude); 12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!entered && inProximity) { 1209105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (LOCAL_LOGV) { 1210105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Log.v(TAG, "Entered alert"); 12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mProximitiesEntered.add(alert); 12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent enteredIntent = new Intent(); 12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project enteredIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, true); 12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 12160528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood synchronized (this) { 12170528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood // synchronize to ensure incrementPendingBroadcasts() 121848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // is called before decrementPendingBroadcasts() 121948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood intent.send(mContext, 0, enteredIntent, this, mLocationHandler); 122048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // call this after broadcasting so we do not increment 122148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // if we throw an exeption. 12220528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood incrementPendingBroadcasts(); 122348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (PendingIntent.CanceledException e) { 1225105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (LOCAL_LOGV) { 1226105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Log.v(TAG, "Canceled proximity alert: " + alert, e); 12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (intentsToRemove == null) { 12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intentsToRemove = new ArrayList<PendingIntent>(); 12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intentsToRemove.add(intent); 12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (entered && !inProximity) { 1234105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (LOCAL_LOGV) { 1235105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Log.v(TAG, "Exited alert"); 12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mProximitiesEntered.remove(alert); 12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent exitedIntent = new Intent(); 12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project exitedIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, false); 12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 12410528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood synchronized (this) { 12420528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood // synchronize to ensure incrementPendingBroadcasts() 124348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // is called before decrementPendingBroadcasts() 124448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood intent.send(mContext, 0, exitedIntent, this, mLocationHandler); 124548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // call this after broadcasting so we do not increment 124648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood // if we throw an exeption. 12470528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood incrementPendingBroadcasts(); 124848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (PendingIntent.CanceledException e) { 1250105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (LOCAL_LOGV) { 1251105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Log.v(TAG, "Canceled proximity alert: " + alert, e); 12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (intentsToRemove == null) { 12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intentsToRemove = new ArrayList<PendingIntent>(); 12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intentsToRemove.add(intent); 12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Mark alert for expiration 1261105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (LOCAL_LOGV) { 1262105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Log.v(TAG, "Expiring proximity alert: " + alert); 12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (intentsToRemove == null) { 12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intentsToRemove = new ArrayList<PendingIntent>(); 12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intentsToRemove.add(alert.getIntent()); 12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Remove expired alerts 12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (intentsToRemove != null) { 12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (PendingIntent i : intentsToRemove) { 12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mProximityAlerts.remove(i); 12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ProximityAlert alert = mProximityAlerts.get(i); 12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mProximitiesEntered.remove(alert); 12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Note: this is called with the lock held. 12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onProviderDisabled(String provider) { 12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (provider.equals(LocationManager.GPS_PROVIDER)) { 12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project isGpsAvailable = false; 12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Note: this is called with the lock held. 12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onProviderEnabled(String provider) { 12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ignore 12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Note: this is called with the lock held. 12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onStatusChanged(String provider, int status, Bundle extras) { 12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((provider.equals(LocationManager.GPS_PROVIDER)) && 12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (status != LocationProvider.AVAILABLE)) { 12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project isGpsAvailable = false; 12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 130148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood 130248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood public void onSendFinished(PendingIntent pendingIntent, Intent intent, 130348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood int resultCode, String resultData, Bundle resultExtras) { 13040528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood // synchronize to ensure incrementPendingBroadcasts() 13050528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood // is called before decrementPendingBroadcasts() 13060528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood synchronized (this) { 13070528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood decrementPendingBroadcasts(); 13080528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood } 130948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void addProximityAlert(double latitude, double longitude, 13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float radius, long expiration, PendingIntent intent) { 13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 13152f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addProximityAlertLocked(latitude, longitude, radius, expiration, intent); 13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SecurityException se) { 13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw se; 13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "addProximityAlert got exception:", e); 13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void addProximityAlertLocked(double latitude, double longitude, 13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float radius, long expiration, PendingIntent intent) { 1327105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (LOCAL_LOGV) { 1328105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Log.v(TAG, "addProximityAlert: latitude = " + latitude + 13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ", longitude = " + longitude + 13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ", expiration = " + expiration + 13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ", intent = " + intent); 13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Require ability to access all providers for now 13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isAllowedProviderSafe(LocationManager.GPS_PROVIDER) || 13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project !isAllowedProviderSafe(LocationManager.NETWORK_PROVIDER)) { 13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires ACCESS_FINE_LOCATION permission"); 13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (expiration != -1) { 13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project expiration += System.currentTimeMillis(); 13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ProximityAlert alert = new ProximityAlert(Binder.getCallingUid(), 13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project latitude, longitude, radius, expiration, intent); 13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mProximityAlerts.put(intent, alert); 13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 134748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood if (mProximityReceiver == null) { 134848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood mProximityListener = new ProximityListener(); 134948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood mProximityReceiver = new Receiver(mProximityListener); 13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 135195427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood for (int i = mProviders.size() - 1; i >= 0; i--) { 135295427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood LocationProviderProxy provider = mProviders.get(i); 135348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver); 13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeProximityAlert(PendingIntent intent) { 13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 13602f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeProximityAlertLocked(intent); 13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SecurityException se) { 13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw se; 13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "removeProximityAlert got exception:", e); 13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void removeProximityAlertLocked(PendingIntent intent) { 1371105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (LOCAL_LOGV) { 1372105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project Log.v(TAG, "removeProximityAlert: intent = " + intent); 13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mProximityAlerts.remove(intent); 13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mProximityAlerts.size() == 0) { 137748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood removeUpdatesLocked(mProximityReceiver); 137848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood mProximityReceiver = null; 13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mProximityListener = null; 13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return null if the provider does not exits 13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throw SecurityException if the provider is not allowed to be 13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * accessed by the caller 13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Bundle getProviderInfo(String provider) { 13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 13902f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return _getProviderInfoLocked(provider); 13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SecurityException se) { 13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw se; 13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "_getProviderInfo got exception:", e); 13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Bundle _getProviderInfoLocked(String provider) { 140215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood LocationProviderProxy p = mProvidersByName.get(provider); 14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (p == null) { 14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkPermissionsSafe(provider); 14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Bundle b = new Bundle(); 14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b.putBoolean("network", p.requiresNetwork()); 14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b.putBoolean("satellite", p.requiresSatellite()); 14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b.putBoolean("cell", p.requiresCell()); 14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b.putBoolean("cost", p.hasMonetaryCost()); 14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b.putBoolean("altitude", p.supportsAltitude()); 14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b.putBoolean("speed", p.supportsSpeed()); 14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b.putBoolean("bearing", p.supportsBearing()); 14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b.putInt("power", p.getPowerRequirement()); 14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b.putInt("accuracy", p.getAccuracy()); 14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return b; 14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isProviderEnabled(String provider) { 14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 14252f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return _isProviderEnabledLocked(provider); 14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SecurityException se) { 14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw se; 14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "isProviderEnabled got exception:", e); 14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1436275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood public void reportLocation(Location location) { 1437275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER) 1438275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood != PackageManager.PERMISSION_GRANTED) { 1439275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission"); 1440275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood } 1441275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood 14424e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location); 14434e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location); 14444e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood mLocationHandler.sendMessageAtFrontOfQueue(m); 14454e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood } 14464e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood 14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean _isProviderEnabledLocked(String provider) { 14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkPermissionsSafe(provider); 14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 145015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood LocationProviderProxy p = mProvidersByName.get(provider); 14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (p == null) { 14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("provider=" + provider); 14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return isAllowedBySettingsLocked(provider); 14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Location getLastKnownLocation(String provider) { 14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 14592f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return _getLastKnownLocationLocked(provider); 14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SecurityException se) { 14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw se; 14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "getLastKnownLocation got exception:", e); 14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Location _getLastKnownLocationLocked(String provider) { 14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkPermissionsSafe(provider); 14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 147315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood LocationProviderProxy p = mProvidersByName.get(provider); 14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (p == null) { 14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("provider=" + provider); 14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isAllowedBySettingsLocked(provider)) { 14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Location location = mLastKnownLocation.get(provider); 14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (location == null) { 14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the persistent last known location for the provider 14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project location = readLastKnownLocationLocked(provider); 14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (location != null) { 14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLastKnownLocation.put(provider, location); 14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return location; 14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static boolean shouldBroadcastSafe(Location loc, Location lastLoc, UpdateRecord record) { 14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Always broadcast the first update 14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lastLoc == null) { 14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Don't broadcast same location again regardless of condition 15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO - we should probably still rebroadcast if user explicitly sets a minTime > 0 15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (loc.getTime() == lastLoc.getTime()) { 15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check whether sufficient distance has been traveled 15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double minDistance = record.mMinDistance; 15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (minDistance > 0.0) { 15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (loc.distanceTo(lastLoc) <= minDistance) { 15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15174e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood private void handleLocationChangedLocked(Location location) { 15184e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood String provider = location.getProvider(); 15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (records == null || records.size() == 0) { 15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 152415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood LocationProviderProxy p = mProvidersByName.get(provider); 15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (p == null) { 15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15294e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood // Update last known location for provider 15304e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood Location lastLocation = mLastKnownLocation.get(provider); 15314e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood if (lastLocation == null) { 15324e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood mLastKnownLocation.put(provider, new Location(location)); 15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 15344e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood lastLocation.set(location); 15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15364e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood writeLastKnownLocationLocked(provider, location); 15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Fetch latest status update time 15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long newStatusUpdateTime = p.getStatusUpdateTime(); 15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15417ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood // Get latest status 15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Bundle extras = new Bundle(); 15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int status = p.getStatus(extras); 15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Receiver> deadReceivers = null; 15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Broadcast location or status to all listeners 15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int N = records.size(); 15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<N; i++) { 15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project UpdateRecord r = records.get(i); 15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Receiver receiver = r.mReceiver; 15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15532f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood Location lastLoc = r.mLastFixBroadcast; 15544e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood if ((lastLoc == null) || shouldBroadcastSafe(location, lastLoc, r)) { 15554e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood if (lastLoc == null) { 15564e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood lastLoc = new Location(location); 15572f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood r.mLastFixBroadcast = lastLoc; 15584e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood } else { 15594e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood lastLoc.set(location); 15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15614e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood if (!receiver.callLocationChangedLocked(location)) { 15624e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood Log.w(TAG, "RemoteException calling onLocationChanged on " + receiver); 15634e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood if (deadReceivers == null) { 15644e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood deadReceivers = new ArrayList<Receiver>(); 15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15664e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood deadReceivers.add(receiver); 15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15702f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood long prevStatusUpdateTime = r.mLastStatusBroadcast; 15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((newStatusUpdateTime > prevStatusUpdateTime) && 15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) { 15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15742f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood r.mLastStatusBroadcast = newStatusUpdateTime; 15759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!receiver.callStatusChangedLocked(provider, status, extras)) { 15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "RemoteException calling onStatusChanged on " + receiver); 15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (deadReceivers == null) { 15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project deadReceivers = new ArrayList<Receiver>(); 15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!deadReceivers.contains(receiver)) { 15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project deadReceivers.add(receiver); 15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (deadReceivers != null) { 15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=deadReceivers.size()-1; i>=0; i--) { 15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeUpdatesLocked(deadReceivers.get(i)); 15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class LocationWorkerHandler extends Handler { 15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 15994e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood if (msg.what == MESSAGE_LOCATION_CHANGED) { 16004e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood // log("LocationWorkerHandler: MESSAGE_LOCATION_CHANGED!"); 16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16022f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 16034e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood Location location = (Location) msg.obj; 1604fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood String provider = location.getProvider(); 160598cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood 1606fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood // notify other providers of the new location 1607fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood for (int i = mProviders.size() - 1; i >= 0; i--) { 1608fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood LocationProviderProxy proxy = mProviders.get(i); 1609fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood if (!provider.equals(proxy.getName())) { 1610fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood proxy.updateLocation(location); 161198cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood } 161298cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood } 161398cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood 1614fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood if (isAllowedBySettingsLocked(provider)) { 1615fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood handleLocationChangedLocked(location); 16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Log, don't crash! 16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Exception in LocationWorkerHandler.handleMessage:", e); 16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16260528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 16270528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood @Override 16280528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood public void onReceive(Context context, Intent intent) { 16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String action = intent.getAction(); 16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16310528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood if (action.equals(Intent.ACTION_PACKAGE_REMOVED) 16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || action.equals(Intent.ACTION_PACKAGE_RESTARTED)) { 16332f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); 16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uid >= 0) { 16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<Receiver> removedRecs = null; 16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (ArrayList<UpdateRecord> i : mRecordsByProvider.values()) { 16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j=i.size()-1; j>=0; j--) { 16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project UpdateRecord ur = i.get(j); 16409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ur.mReceiver.isPendingIntent() && ur.mUid == uid) { 16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (removedRecs == null) { 16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removedRecs = new ArrayList<Receiver>(); 16439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!removedRecs.contains(ur.mReceiver)) { 16459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removedRecs.add(ur.mReceiver); 16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<ProximityAlert> removedAlerts = null; 16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (ProximityAlert i : mProximityAlerts.values()) { 16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (i.mUid == uid) { 16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (removedAlerts == null) { 16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removedAlerts = new ArrayList<ProximityAlert>(); 16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!removedAlerts.contains(i)) { 16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removedAlerts.add(i); 16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (removedRecs != null) { 16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=removedRecs.size()-1; i>=0; i--) { 16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeUpdatesLocked(removedRecs.get(i)); 16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (removedAlerts != null) { 16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=removedAlerts.size()-1; i>=0; i--) { 16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeProximityAlertLocked(removedAlerts.get(i).mIntent); 16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16730528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean noConnectivity = 16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); 16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!noConnectivity) { 16774df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project mNetworkState = LocationProvider.AVAILABLE; 16784df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } else { 16794df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE; 16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Notify location providers of current network state 16832f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 168415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood for (int i = mProviders.size() - 1; i >= 0; i--) { 168515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood LocationProviderProxy provider = mProviders.get(i); 16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (provider.requiresNetwork()) { 16874df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project provider.updateNetworkState(mNetworkState); 16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16930528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood }; 16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Wake locks 16969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16970528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood private void incrementPendingBroadcasts() { 16980528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood synchronized (mWakeLock) { 16990528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood if (mPendingBroadcasts++ == 0) { 17000528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood try { 17010528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood mWakeLock.acquire(); 17020528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood log("Acquired wakelock"); 17030528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood } catch (Exception e) { 17040528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood // This is to catch a runtime exception thrown when we try to release an 17050528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood // already released lock. 17060528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood Log.e(TAG, "exception in acquireWakeLock()", e); 17070528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood } 17080528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood } 170948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 171048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 171148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood 171248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood private void decrementPendingBroadcasts() { 17130528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood synchronized (mWakeLock) { 171448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood if (--mPendingBroadcasts == 0) { 17150528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood try { 17160528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood // Release wake lock 17170528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood if (mWakeLock.isHeld()) { 17180528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood mWakeLock.release(); 17190528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood log("Released wakelock"); 17200528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood } else { 17210528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood log("Can't release wakelock again!"); 17220528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood } 17230528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood } catch (Exception e) { 17240528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood // This is to catch a runtime exception thrown when we try to release an 17250528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood // already released lock. 17260528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood Log.e(TAG, "exception in releaseWakeLock()", e); 17270528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood } 172848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 172948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 173048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood } 173148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood 17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Geocoder 17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getFromLocation(double latitude, double longitude, int maxResults, 1735a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood String language, String country, String variant, String appName, List<Address> addrs) { 1736a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood if (mGeocodeProvider != null) { 1737a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood try { 1738a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, language, country, 1739a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood variant, appName, addrs); 1740a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood } catch (RemoteException e) { 1741a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood Log.e(TAG, "getFromLocation failed", e); 17423681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood mGeocodeProvider = null; 17439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1745a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood return null; 17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1748a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood 17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getFromLocationName(String locationName, 1750a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood double lowerLeftLatitude, double lowerLeftLongitude, 1751a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood double upperRightLatitude, double upperRightLongitude, int maxResults, 1752a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood String language, String country, String variant, String appName, List<Address> addrs) { 1753a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood 1754a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood if (mGeocodeProvider != null) { 1755a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood try { 1756a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude, 1757a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood lowerLeftLongitude, upperRightLatitude, upperRightLongitude, 1758a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood maxResults, language, country, variant, appName, addrs); 1759a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood } catch (RemoteException e) { 1760a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood Log.e(TAG, "getFromLocationName failed", e); 17613681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood mGeocodeProvider = null; 17629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1764a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood return null; 17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Mock Providers 17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void checkMockPermissionsSafe() { 17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(), 17719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1; 17729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!allowMocks) { 17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting"); 17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) != 17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PackageManager.PERMISSION_GRANTED) { 17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission"); 17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite, 17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude, 17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) { 17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkMockPermissionsSafe(); 17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17872f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 17884e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood MockProvider provider = new MockProvider(name, this, 17894e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood requiresNetwork, requiresSatellite, 17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requiresCell, hasMonetaryCost, supportsAltitude, 17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project supportsSpeed, supportsBearing, powerRequirement, accuracy); 179215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood if (mProvidersByName.get(name) != null) { 17939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Provider \"" + name + "\" already exists"); 17949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 179595427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood 179695427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required 179795427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood long identity = Binder.clearCallingIdentity(); 179815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood addProvider(new LocationProviderProxy(name, provider)); 17997ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood mMockProviders.put(name, provider); 18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateProvidersLocked(); 180195427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood Binder.restoreCallingIdentity(identity); 18029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeTestProvider(String provider) { 18069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkMockPermissionsSafe(); 18072f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 18087ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood MockProvider mockProvider = mMockProviders.get(provider); 18097ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood if (mockProvider == null) { 18109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 18119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 181215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood removeProvider(mProvidersByName.get(provider)); 18137ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood mMockProviders.remove(mockProvider); 18149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateProvidersLocked(); 18159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setTestProviderLocation(String provider, Location loc) { 18199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkMockPermissionsSafe(); 18202f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 18217ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood MockProvider mockProvider = mMockProviders.get(provider); 18227ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood if (mockProvider == null) { 18239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 18249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 182595427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required 182695427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood long identity = Binder.clearCallingIdentity(); 18277ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood mockProvider.setLocation(loc); 182895427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood Binder.restoreCallingIdentity(identity); 18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void clearTestProviderLocation(String provider) { 18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkMockPermissionsSafe(); 18342f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 18357ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood MockProvider mockProvider = mMockProviders.get(provider); 18367ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood if (mockProvider == null) { 18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 18389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18397ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood mockProvider.clearLocation(); 18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setTestProviderEnabled(String provider, boolean enabled) { 18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkMockPermissionsSafe(); 18452f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 18467ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood MockProvider mockProvider = mMockProviders.get(provider); 18477ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood if (mockProvider == null) { 18489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 18499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (enabled) { 18517ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood mockProvider.enable(); 18529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEnabledProviders.add(provider); 18539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDisabledProviders.remove(provider); 18549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 18557ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood mockProvider.disable(); 18569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEnabledProviders.remove(provider); 18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDisabledProviders.add(provider); 18589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateProvidersLocked(); 18609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void clearTestProviderEnabled(String provider) { 18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkMockPermissionsSafe(); 18652f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 18667ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood MockProvider mockProvider = mMockProviders.get(provider); 18677ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood if (mockProvider == null) { 18689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 18699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEnabledProviders.remove(provider); 18719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDisabledProviders.remove(provider); 18729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateProvidersLocked(); 18739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) { 18779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkMockPermissionsSafe(); 18782f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 18797ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood MockProvider mockProvider = mMockProviders.get(provider); 18807ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood if (mockProvider == null) { 18819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 18829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18837ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood mockProvider.setStatus(status, extras, updateTime); 18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void clearTestProviderStatus(String provider) { 18889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkMockPermissionsSafe(); 18892f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 18907ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood MockProvider mockProvider = mMockProviders.get(provider); 18917ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood if (mockProvider == null) { 18929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 18939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18947ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood mockProvider.clearStatus(); 18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void log(String log) { 18999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Log.isLoggable(TAG, Log.VERBOSE)) { 19009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.d(TAG, log); 19019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 19059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 19069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 19070528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood pw.println("Permission Denial: can't dump LocationManagerService from from pid=" 19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + Binder.getCallingPid() 19099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ", uid=" + Binder.getCallingUid()); 19109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 19119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19132f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood synchronized (mLock) { 19149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println("Current Location Manager state:"); 19159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" sProvidersLoaded=" + sProvidersLoaded); 19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" Listeners:"); 19172f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood int N = mReceivers.size(); 19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<N; i++) { 19192f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood pw.println(" " + mReceivers.get(i)); 19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" Location Listeners:"); 19222f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood for (Receiver i : mReceivers.values()) { 19232f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood pw.println(" " + i + ":"); 19242f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood for (Map.Entry<String,UpdateRecord> j : i.mUpdateRecords.entrySet()) { 19259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" " + j.getKey() + ":"); 19269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project j.getValue().dump(pw, " "); 19279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" Records by Provider:"); 19309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Map.Entry<String, ArrayList<UpdateRecord>> i 19319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : mRecordsByProvider.entrySet()) { 19329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" " + i.getKey() + ":"); 19339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (UpdateRecord j : i.getValue()) { 19349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" " + j + ":"); 19359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project j.dump(pw, " "); 19369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" Last Known Locations:"); 19399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Map.Entry<String, Location> i 19409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : mLastKnownLocation.entrySet()) { 19419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" " + i.getKey() + ":"); 19429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i.getValue().dump(new PrintWriterPrinter(pw), " "); 19439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mProximityAlerts.size() > 0) { 19459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" Proximity Alerts:"); 19469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Map.Entry<PendingIntent, ProximityAlert> i 19479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : mProximityAlerts.entrySet()) { 19489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" " + i.getKey() + ":"); 19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i.getValue().dump(pw, " "); 19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mProximitiesEntered.size() > 0) { 19539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" Proximities Entered:"); 19549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (ProximityAlert i : mProximitiesEntered) { 19559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" " + i + ":"); 19569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i.dump(pw, " "); 19579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 195948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood pw.println(" mProximityReceiver=" + mProximityReceiver); 19609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" mProximityListener=" + mProximityListener); 19619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEnabledProviders.size() > 0) { 19629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" Enabled Providers:"); 19639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String i : mEnabledProviders) { 19649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" " + i); 19659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDisabledProviders.size() > 0) { 19699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" Disabled Providers:"); 19709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String i : mDisabledProviders) { 19719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" " + i); 19729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMockProviders.size() > 0) { 19769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pw.println(" Mock Providers:"); 19779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) { 19787ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood i.getValue().dump(pw, " "); 19799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1984