LocationManagerService.java revision 080b61ba17014b8c93914f642ccbe05c76dc611d
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.FileDescriptor;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashSet;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map;
269637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwoodimport java.util.Observable;
279637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwoodimport java.util.Observer;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.PendingIntent;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver;
329637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwoodimport android.content.ContentQueryMap;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
389637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwoodimport android.database.Cursor;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Address;
40a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwoodimport android.location.IGeocodeProvider;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.IGpsStatusListener;
4215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwoodimport android.location.IGpsStatusProvider;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.ILocationListener;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.ILocationManager;
45e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwoodimport android.location.ILocationProvider;
4622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport android.location.INetInitiatedListener;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Location;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationManager;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationProvider;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.ConnectivityManager;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
563d12b51ee38537f6760a833618948f936e75561dMike Lockwoodimport android.os.Looper;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager;
59e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwoodimport android.os.Process;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.PrintWriterPrinter;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.location.GpsLocationProvider;
66e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwoodimport com.android.internal.location.LocationProviderProxy;
677ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwoodimport com.android.internal.location.MockProvider;
6822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport com.android.internal.location.GpsNetInitiatedHandler;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The service class that manages LocationProviders and issues location
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * updates and alerts.
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
763d12b51ee38537f6760a833618948f936e75561dMike Lockwoodpublic class LocationManagerService extends ILocationManager.Stub implements Runnable {
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "LocationManagerService";
78105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final boolean LOCAL_LOGV = false;
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // The last time a location was written, by provider name.
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<String,Long> mLastWriteTime = new HashMap<String,Long>();
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_FINE_LOCATION =
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        android.Manifest.permission.ACCESS_FINE_LOCATION;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_COARSE_LOCATION =
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        android.Manifest.permission.ACCESS_COARSE_LOCATION;
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_MOCK_LOCATION =
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        android.Manifest.permission.ACCESS_MOCK_LOCATION;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
91275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood    private static final String INSTALL_LOCATION_PROVIDER =
92275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Set of providers that are explicitly enabled
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Set<String> mEnabledProviders = new HashSet<String>();
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Set of providers that are explicitly disabled
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Set<String> mDisabledProviders = new HashSet<String>();
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Locations, status values, and extras for mock providers
1017ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood    private final HashMap<String,MockProvider> mMockProviders = new HashMap<String,MockProvider>();
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean sProvidersLoaded = false;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Context mContext;
106a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood    private IGeocodeProvider mGeocodeProvider;
10715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private IGpsStatusProvider mGpsStatusProvider;
10822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private INetInitiatedListener mNetInitiatedListener;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private LocationWorkerHandler mLocationHandler;
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1117566c1debebe072af76411e11d96810fd1409482Mike Lockwood    // Cache the real providers for use in addTestProvider() and removeTestProvider()
1127566c1debebe072af76411e11d96810fd1409482Mike Lockwood     LocationProviderProxy mNetworkLocationProvider;
1137566c1debebe072af76411e11d96810fd1409482Mike Lockwood     LocationProviderProxy mGpsLocationProvider;
1147566c1debebe072af76411e11d96810fd1409482Mike Lockwood
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Handler messages
1164e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    private static final int MESSAGE_LOCATION_CHANGED = 1;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1180528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    // wakelock variables
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final static String WAKELOCK_KEY = "LocationManagerService";
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private PowerManager.WakeLock mWakeLock = null;
12148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private int mPendingBroadcasts;
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1242f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood     * List of all receivers.
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1262f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final HashMap<Object, Receiver> mReceivers = new HashMap<Object, Receiver>();
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
12915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    /**
13015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood     * List of location providers.
13115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood     */
13215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final ArrayList<LocationProviderProxy> mProviders =
13315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        new ArrayList<LocationProviderProxy>();
13415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final HashMap<String, LocationProviderProxy> mProvidersByName
13515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        = new HashMap<String, LocationProviderProxy>();
13615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1382f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood     * Object used internally for synchronization
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1402f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final Object mLock = new Object();
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Mapping from provider name to all its UpdateRecords
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashMap<String,ArrayList<UpdateRecord>> mRecordsByProvider =
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashMap<String,ArrayList<UpdateRecord>>();
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Proximity listeners
14948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private Receiver mProximityReceiver = null;
15048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private ILocationListener mProximityListener = null;
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<PendingIntent,ProximityAlert> mProximityAlerts =
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashMap<PendingIntent,ProximityAlert>();
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashSet<ProximityAlert> mProximitiesEntered =
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashSet<ProximityAlert>();
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Last known location for each provider
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<String,Location> mLastKnownLocation =
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashMap<String,Location>();
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1604df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    private int mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
1614df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
1629637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood    // for Settings change notification
1639637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood    private ContentQueryMap mSettings;
1649637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A wrapper class holding either an ILocationListener or a PendingIntent to receive
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * location updates.
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ILocationListener mListener;
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final PendingIntent mPendingIntent;
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Object mKey;
1732f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
17448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        int mPendingBroadcasts;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1762f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver(ILocationListener listener) {
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = listener;
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPendingIntent = null;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mKey = listener.asBinder();
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1822f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver(PendingIntent intent) {
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPendingIntent = intent;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = null;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mKey = intent;
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean equals(Object otherObj) {
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (otherObj instanceof Receiver) {
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mKey.equals(
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((Receiver)otherObj).mKey);
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int hashCode() {
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mKey.hashCode();
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2013681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return "Receiver{"
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + Integer.toHexString(System.identityHashCode(this))
2072f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                        + " Listener " + mKey + "}";
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return "Receiver{"
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + Integer.toHexString(System.identityHashCode(this))
2112f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                        + " Intent " + mKey + "}";
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean isListener() {
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mListener != null;
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean isPendingIntent() {
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mPendingIntent != null;
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ILocationListener getListener() {
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mListener;
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("Request for non-existent listener");
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public PendingIntent getPendingIntent() {
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mPendingIntent != null) {
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mPendingIntent;
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("Request for non-existent intent");
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
24048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
24148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
24248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
24348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mListener.onStatusChanged(provider, status, extras);
24448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (mListener != mProximityListener) {
24548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // call this after broadcasting so we do not increment
24648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // if we throw an exeption.
24748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            incrementPendingBroadcastsLocked();
24848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
24948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent statusChanged = new Intent();
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                statusChanged.putExtras(extras);
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
25848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
25948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
26048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
26148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler);
26248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
26348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
26448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
26548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (PendingIntent.CanceledException e) {
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean callLocationChangedLocked(Location location) {
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
27648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
27748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
27848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
27948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mListener.onLocationChanged(location);
28048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (mListener != mProximityListener) {
28148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // call this after broadcasting so we do not increment
28248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // if we throw an exeption.
28348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            incrementPendingBroadcastsLocked();
28448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
28548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent locationChanged = new Intent();
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, location);
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
29348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
29448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
29548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
29648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler);
29748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
29848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
29948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
30048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
30148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                } catch (PendingIntent.CanceledException e) {
30248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    return false;
30348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
30448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
30548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            return true;
30648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
30748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
30848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        public boolean callProviderEnabledLocked(String provider, boolean enabled) {
30948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (mListener != null) {
31048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                try {
31148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
31248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
31348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
31448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (enabled) {
31548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            mListener.onProviderEnabled(provider);
31648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        } else {
31748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            mListener.onProviderDisabled(provider);
31848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
31948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (mListener != mProximityListener) {
32048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // call this after broadcasting so we do not increment
32148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // if we throw an exeption.
32248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            incrementPendingBroadcastsLocked();
32348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
32448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
32548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                } catch (RemoteException e) {
32648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    return false;
32748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
32848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            } else {
32948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                Intent providerIntent = new Intent();
33048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
33148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                try {
33248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
33348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
33448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
33548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler);
33648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
33748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
33848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
33948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (PendingIntent.CanceledException e) {
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
348105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            if (LOCAL_LOGV) {
349105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                Log.v(TAG, "Location listener died");
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3512f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeUpdatesLocked(this);
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
35448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            synchronized (this) {
35548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                if (mPendingBroadcasts > 0) {
35648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    LocationManagerService.this.decrementPendingBroadcasts();
35748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    mPendingBroadcasts = 0;
35848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
35948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
36048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
36148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
36248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        public void onSendFinished(PendingIntent pendingIntent, Intent intent,
36348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                int resultCode, String resultData, Bundle resultExtras) {
3640528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            synchronized (this) {
3650528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                decrementPendingBroadcastsLocked();
3660528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
36748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
36848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
3690528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // this must be called while synchronized by caller in a synchronized block
37048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        // containing the sending of the broadcaset
37148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        private void incrementPendingBroadcastsLocked() {
37248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (mPendingBroadcasts++ == 0) {
3730528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                LocationManagerService.this.incrementPendingBroadcasts();
37448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
37548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
37648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
3770528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        private void decrementPendingBroadcastsLocked() {
3780528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (--mPendingBroadcasts == 0) {
3790528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                LocationManagerService.this.decrementPendingBroadcasts();
38048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
38148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
38248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
38348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
38448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    public void locationCallbackFinished(ILocationListener listener) {
385080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //Do not use getReceiver here as that will add the ILocationListener to
386080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //the receiver list if it is not found.  If it is not found then the
387080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //LocationListener was removed when it had a pending broadcast and should
388080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //not be added back.
389080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        IBinder binder = listener.asBinder();
390080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        Receiver receiver = mReceivers.get(binder);
39148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        if (receiver != null) {
3920528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            synchronized (receiver) {
3930528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                // so wakelock calls will succeed
3940528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                long identity = Binder.clearCallingIdentity();
3950528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                receiver.decrementPendingBroadcastsLocked();
3960528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                Binder.restoreCallingIdentity(identity);
3970528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood           }
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4019637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood    private final class SettingsObserver implements Observer {
4029637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        public void update(Observable o, Object arg) {
4032f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
4049637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood                updateProvidersLocked();
4059637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood            }
4069637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        }
4079637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood    }
4089637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood
40915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private void addProvider(LocationProviderProxy provider) {
41015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProviders.add(provider);
41115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProvidersByName.put(provider.getName(), provider);
41215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
41315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
41415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private void removeProvider(LocationProviderProxy provider) {
41515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProviders.remove(provider);
416fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu        provider.unlinkProvider();
41715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProvidersByName.remove(provider.getName());
41815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
41915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void loadProviders() {
4212f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sProvidersLoaded) {
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Load providers
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            loadProvidersLocked();
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sProvidersLoaded = true;
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void loadProvidersLocked() {
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            _loadProvidersLocked();
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "Exception loading providers:", e);
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void _loadProvidersLocked() {
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Attempt to load "real" providers first
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (GpsLocationProvider.isSupported()) {
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Create a gps location provider
44415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            GpsLocationProvider provider = new GpsLocationProvider(mContext, this);
44515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            mGpsStatusProvider = provider.getGpsStatusProvider();
44622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            mNetInitiatedListener = provider.getNetInitiatedListener();
4478dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood            LocationProviderProxy proxy = new LocationProviderProxy(LocationManager.GPS_PROVIDER, provider);
4488dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood            addProvider(proxy);
4497566c1debebe072af76411e11d96810fd1409482Mike Lockwood            mGpsLocationProvider = proxy;
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateProvidersLocked();
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context the context that the LocationManagerService runs in
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public LocationManagerService(Context context) {
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super();
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
4613d12b51ee38537f6760a833618948f936e75561dMike Lockwood
4623d12b51ee38537f6760a833618948f936e75561dMike Lockwood        Thread thread = new Thread(null, this, "LocationManagerService");
4633d12b51ee38537f6760a833618948f936e75561dMike Lockwood        thread.start();
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
465105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
466105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "Constructed LocationManager Service");
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4683d12b51ee38537f6760a833618948f936e75561dMike Lockwood    }
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4703d12b51ee38537f6760a833618948f936e75561dMike Lockwood    private void initialize() {
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Create a wake lock, needs to be done before calling loadProviders() below
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
4740528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Load providers
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        loadProviders();
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Register for Network (Wifi or Mobile) updates
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IntentFilter intentFilter = new IntentFilter();
4800528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
4810528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // Register for Package Manager updates
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
4840528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        mContext.registerReceiver(mBroadcastReceiver, intentFilter);
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4869637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        // listen for settings changes
4879637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        ContentResolver resolver = mContext.getContentResolver();
4889637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        Cursor settingsCursor = resolver.query(Settings.Secure.CONTENT_URI, null,
4899637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood                "(" + Settings.System.NAME + "=?)",
4909637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood                new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
4919637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood                null);
4929637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mLocationHandler);
4939637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        SettingsObserver settingsObserver = new SettingsObserver();
4949637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        mSettings.addObserver(settingsObserver);
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4973d12b51ee38537f6760a833618948f936e75561dMike Lockwood    public void run()
4983d12b51ee38537f6760a833618948f936e75561dMike Lockwood    {
4993d12b51ee38537f6760a833618948f936e75561dMike Lockwood        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
5003d12b51ee38537f6760a833618948f936e75561dMike Lockwood        Looper.prepare();
5013d12b51ee38537f6760a833618948f936e75561dMike Lockwood        mLocationHandler = new LocationWorkerHandler();
5023d12b51ee38537f6760a833618948f936e75561dMike Lockwood        initialize();
5033d12b51ee38537f6760a833618948f936e75561dMike Lockwood        Looper.loop();
5043d12b51ee38537f6760a833618948f936e75561dMike Lockwood    }
5053d12b51ee38537f6760a833618948f936e75561dMike Lockwood
506275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood    public void installLocationProvider(String name, ILocationProvider provider) {
507275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
508275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood                != PackageManager.PERMISSION_GRANTED) {
509275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood            throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
510e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwood        }
511e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwood
5122f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
5133681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood            // check to see if we are reinstalling a dead provider
5143681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood            LocationProviderProxy oldProvider = mProvidersByName.get(name);
5153681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood            if (oldProvider != null) {
5163681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood                if (oldProvider.isDead()) {
5173681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood                    Log.d(TAG, "replacing dead provider");
5183681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood                    removeProvider(oldProvider);
5193681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood                } else {
5203681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood                    throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
5213681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood                }
5223681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood            }
5233681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood
5248dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood            LocationProviderProxy proxy = new LocationProviderProxy(name, provider);
5258dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood            addProvider(proxy);
5268dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood            updateProvidersLocked();
5277566c1debebe072af76411e11d96810fd1409482Mike Lockwood            if (LocationManager.NETWORK_PROVIDER.equals(name)) {
5287566c1debebe072af76411e11d96810fd1409482Mike Lockwood                mNetworkLocationProvider = proxy;
5297566c1debebe072af76411e11d96810fd1409482Mike Lockwood            }
530275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood
5318dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood            // notify provider of current network state
5328dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood            proxy.updateNetworkState(mNetworkState);
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
536275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood    public void installGeocodeProvider(IGeocodeProvider provider) {
537275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
538275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood                != PackageManager.PERMISSION_GRANTED) {
539275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood            throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
540a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        }
541a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood
542a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        mGeocodeProvider = provider;
543a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood    }
544a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean isAllowedBySettingsLocked(String provider) {
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabledProviders.contains(provider)) {
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDisabledProviders.contains(provider)) {
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Use system settings
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ContentResolver resolver = mContext.getContentResolver();
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String allowedProviders = Settings.Secure.getString(resolver,
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project           Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ((allowedProviders != null) && (allowedProviders.contains(provider)));
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void checkPermissionsSafe(String provider) {
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (LocationManager.GPS_PROVIDER.equals(provider)
562b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (LocationManager.NETWORK_PROVIDER.equals(provider)
567b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)
569b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION)
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException(
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "Requires ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission");
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean isAllowedProviderSafe(String provider) {
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (LocationManager.GPS_PROVIDER.equals(provider)
578b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (LocationManager.NETWORK_PROVIDER.equals(provider)
583b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)
585b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION)
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<String> getAllProviders() {
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
5952f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _getAllProvidersLocked();
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "getAllProviders got exception:", e);
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private List<String> _getAllProvidersLocked() {
607105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
608105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "getAllProviders");
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
61015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        ArrayList<String> out = new ArrayList<String>(mProviders.size());
61115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        for (int i = mProviders.size() - 1; i >= 0; i--) {
61215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            LocationProviderProxy p = mProviders.get(i);
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            out.add(p.getName());
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return out;
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<String> getProviders(boolean enabledOnly) {
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
6202f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _getProvidersLocked(enabledOnly);
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
626105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.e(TAG, "getProviders got exception:", e);
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private List<String> _getProvidersLocked(boolean enabledOnly) {
632105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
633105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "getProviders");
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
63515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        ArrayList<String> out = new ArrayList<String>(mProviders.size());
63615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        for (int i = mProviders.size() - 1; i >= 0; i--) {
63715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            LocationProviderProxy p = mProviders.get(i);
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = p.getName();
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isAllowedProviderSafe(name)) {
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (enabledOnly && !isAllowedBySettingsLocked(name)) {
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                out.add(name);
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return out;
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateProvidersLocked() {
65015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        for (int i = mProviders.size() - 1; i >= 0; i--) {
65115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            LocationProviderProxy p = mProviders.get(i);
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean isEnabled = p.isEnabled();
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = p.getName();
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isEnabled && !shouldBeEnabled) {
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                updateProviderListenersLocked(name, false);
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (!isEnabled && shouldBeEnabled) {
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                updateProviderListenersLocked(name, true);
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateProviderListenersLocked(String provider, boolean enabled) {
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int listeners = 0;
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
66815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        LocationProviderProxy p = mProvidersByName.get(provider);
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<Receiver> deadReceivers = null;
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (records != null) {
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int N = records.size();
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                UpdateRecord record = records.get(i);
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Sends a notification message to the receiver
68148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
68248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    if (deadReceivers == null) {
68348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        deadReceivers = new ArrayList<Receiver>();
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6854686657cee6411eb00235d49b4a8663a96361a00Simon Schoar                    deadReceivers.add(record.mReceiver);
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listeners++;
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (deadReceivers != null) {
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=deadReceivers.size()-1; i>=0; i--) {
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeUpdatesLocked(deadReceivers.get(i));
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (enabled) {
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.enable();
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (listeners > 0) {
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.setMinTime(getMinTimeLocked(provider));
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.enableLocationTracking(true);
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.enableLocationTracking(false);
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.disable();
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long getMinTimeLocked(String provider) {
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long minTime = Long.MAX_VALUE;
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (records != null) {
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=records.size()-1; i>=0; i--) {
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                minTime = Math.min(minTime, records.get(i).mMinTime);
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return minTime;
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class UpdateRecord {
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String mProvider;
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Receiver mReceiver;
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final long mMinTime;
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float mMinDistance;
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int mUid;
7262f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Location mLastFixBroadcast;
7272f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        long mLastStatusBroadcast;
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Note: must be constructed with lock held.
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        UpdateRecord(String provider, long minTime, float minDistance,
7332f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            Receiver receiver, int uid) {
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProvider = provider;
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mReceiver = receiver;
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMinTime = minTime;
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMinDistance = minDistance;
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mUid = uid;
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (records == null) {
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                records = new ArrayList<UpdateRecord>();
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRecordsByProvider.put(provider, records);
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!records.contains(this)) {
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                records.add(this);
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Method to be called when a record will no longer be used.  Calling this multiple times
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * must have the same effect as calling it once.
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void disposeLocked() {
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<UpdateRecord> records = mRecordsByProvider.get(this.mProvider);
7563a76fd627945c1df59aa0318867401e0e53da022Mike Lockwood            if (records != null) {
7573a76fd627945c1df59aa0318867401e0e53da022Mike Lockwood                records.remove(this);
7583a76fd627945c1df59aa0318867401e0e53da022Mike Lockwood            }
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "UpdateRecord{"
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Integer.toHexString(System.identityHashCode(this))
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " " + mProvider + " " + mReceiver + "}";
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void dump(PrintWriter pw, String prefix) {
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + this);
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mProvider=" + mProvider + " mReceiver=" + mReceiver);
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mMinTime=" + mMinTime + " mMinDistance=" + mMinDistance);
7722f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            pw.println(prefix + "mUid=" + mUid);
7732f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            pw.println(prefix + "mLastFixBroadcast:");
7742f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            mLastFixBroadcast.dump(new PrintWriterPrinter(pw), prefix + "  ");
7752f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            pw.println(prefix + "mLastStatusBroadcast=" + mLastStatusBroadcast);
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7792f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private Receiver getReceiver(ILocationListener listener) {
7802f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        IBinder binder = listener.asBinder();
7812f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver receiver = mReceivers.get(binder);
7822f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (receiver == null) {
7832f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            receiver = new Receiver(listener);
7842f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            mReceivers.put(binder, receiver);
7852f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
7862f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            try {
7872f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                if (receiver.isListener()) {
7882f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    receiver.getListener().asBinder().linkToDeath(receiver, 0);
7892f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                }
7902f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            } catch (RemoteException e) {
7912f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                Log.e(TAG, "linkToDeath failed:", e);
7922f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                return null;
7932f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
7942f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
7952f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        return receiver;
7962f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
7972f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
7982f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private Receiver getReceiver(PendingIntent intent) {
7992f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver receiver = mReceivers.get(intent);
8002f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (receiver == null) {
8012f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            receiver = new Receiver(intent);
8022f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            mReceivers.put(intent, receiver);
8032f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
8042f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        return receiver;
8052f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
8062f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8072f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private boolean providerHasListener(String provider, int uid, Receiver excludedReceiver) {
8082f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
8092f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (records != null) {
8102f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            for (int i = records.size() - 1; i >= 0; i--) {
8112f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                UpdateRecord record = records.get(i);
8122f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                if (record.mUid == uid && record.mReceiver != excludedReceiver) {
8132f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    return true;
8142f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                }
8152f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood           }
8162f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
81795427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood        for (ProximityAlert alert : mProximityAlerts.values()) {
81895427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            if (alert.mUid == uid) {
81995427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood                return true;
8202f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
8212f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
8222f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        return false;
8232f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
8242f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void requestLocationUpdates(String provider,
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long minTime, float minDistance, ILocationListener listener) {
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8292f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
8302f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                requestLocationUpdatesLocked(provider, minTime, minDistance, getReceiver(listener));
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "requestUpdates got exception:", e);
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void requestLocationUpdatesPI(String provider,
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long minTime, float minDistance, PendingIntent intent) {
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8422f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
8432f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                requestLocationUpdatesLocked(provider, minTime, minDistance, getReceiver(intent));
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "requestUpdates got exception:", e);
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void requestLocationUpdatesLocked(String provider,
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long minTime, float minDistance, Receiver receiver) {
854105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
855105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "_requestLocationUpdates: listener = " + receiver);
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
85815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        LocationProviderProxy proxy = mProvidersByName.get(provider);
85915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (proxy == null) {
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("provider=" + provider);
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // so wakelock calls will succeed
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int callingUid = Binder.getCallingUid();
8672f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        boolean newUid = !providerHasListener(provider, callingUid, null);
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identity = Binder.clearCallingIdentity();
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8702f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            UpdateRecord r = new UpdateRecord(provider, minTime, minDistance, receiver, callingUid);
8712f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            UpdateRecord oldRecord = receiver.mUpdateRecords.put(provider, r);
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (oldRecord != null) {
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                oldRecord.disposeLocked();
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8762f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            if (newUid) {
87715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                proxy.addListener(callingUid);
8782f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
8792f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean isProviderEnabled = isAllowedBySettingsLocked(provider);
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isProviderEnabled) {
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long minTimeForProvider = getMinTimeLocked(provider);
88315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                proxy.setMinTime(minTimeForProvider);
88415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                proxy.enableLocationTracking(true);
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
88648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                // Notify the listener that updates are currently disabled
88748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                receiver.callProviderEnabledLocked(provider, false);
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(identity);
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeUpdates(ILocationListener listener) {
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8962f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
8972f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                removeUpdatesLocked(getReceiver(listener));
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "removeUpdates got exception:", e);
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeUpdatesPI(PendingIntent intent) {
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
9082f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
9092f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                removeUpdatesLocked(getReceiver(intent));
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "removeUpdates got exception:", e);
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void removeUpdatesLocked(Receiver receiver) {
919105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
920105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "_removeUpdates: listener = " + receiver);
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // so wakelock calls will succeed
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int callingUid = Binder.getCallingUid();
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identity = Binder.clearCallingIdentity();
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
9272f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
9282f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
929080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                synchronized(receiver) {
930080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                    if(receiver.mPendingBroadcasts > 0) {
931080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                        decrementPendingBroadcasts();
932080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                        receiver.mPendingBroadcasts = 0;
933080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                    }
934080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                }
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Record which providers were associated with this listener
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            HashSet<String> providers = new HashSet<String>();
9392f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            HashMap<String,UpdateRecord> oldRecords = receiver.mUpdateRecords;
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (oldRecords != null) {
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Call dispose() on the obsolete update records.
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (UpdateRecord record : oldRecords.values()) {
9432f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    if (!providerHasListener(record.mProvider, callingUid, receiver)) {
94415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        LocationProviderProxy proxy = mProvidersByName.get(record.mProvider);
94515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        if (proxy != null) {
94615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                            proxy.removeListener(callingUid);
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    record.disposeLocked();
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Accumulate providers
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                providers.addAll(oldRecords.keySet());
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // See if the providers associated with this listener have any
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // other listeners; if one does, inform it of the new smallest minTime
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // value; if one does not, disable location tracking for it
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (String provider : providers) {
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // If provider is already disabled, don't need to do anything
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!isAllowedBySettingsLocked(provider)) {
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean hasOtherListener = false;
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ArrayList<UpdateRecord> recordsForProvider = mRecordsByProvider.get(provider);
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (recordsForProvider != null && recordsForProvider.size() > 0) {
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    hasOtherListener = true;
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
97015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                LocationProviderProxy p = mProvidersByName.get(provider);
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (p != null) {
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (hasOtherListener) {
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        p.setMinTime(getMinTimeLocked(provider));
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        p.enableLocationTracking(false);
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(identity);
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean addGpsStatusListener(IGpsStatusListener listener) {
98515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mGpsStatusProvider == null) {
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
988b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood        if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) !=
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PackageManager.PERMISSION_GRANTED) {
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
99415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            mGpsStatusProvider.addGpsStatusListener(listener);
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
99615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            Log.e(TAG, "mGpsStatusProvider.addGpsStatusListener failed", e);
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeGpsStatusListener(IGpsStatusListener listener) {
10032f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
100415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            try {
100515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                mGpsStatusProvider.removeGpsStatusListener(listener);
100615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            } catch (Exception e) {
100715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Log.e(TAG, "mGpsStatusProvider.removeGpsStatusListener failed", e);
100815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendExtraCommand(String provider, String command, Bundle extras) {
1013c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood        if (provider == null) {
1014c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood            // throw NullPointerException to remain compatible with previous implementation
1015c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood            throw new NullPointerException();
1016c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood        }
1017c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // first check for permission to the provider
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // and check for ACCESS_LOCATION_EXTRA_COMMANDS
1021b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood        if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10262f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
102715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            LocationProviderProxy proxy = mProvidersByName.get(provider);
10286ba7ae1e4c3c04f6a71380b913ad79f83b00a628Mike Lockwood            if (proxy == null) {
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
103215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            return proxy.sendExtraCommand(command, extras);
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
103622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    public boolean sendNiResponse(int notifId, int userResponse)
103722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    {
103818ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood        if (Binder.getCallingUid() != Process.myUid()) {
103918ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood            throw new SecurityException(
104018ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood                    "calling sendNiResponse from outside of the system is not allowed");
104118ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood        }
104222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        try {
104322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
104422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        }
104522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        catch (RemoteException e)
104622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        {
104722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            Log.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
104822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            return false;
104922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        }
105022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    }
105122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class ProximityAlert {
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int  mUid;
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final double mLatitude;
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final double mLongitude;
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float mRadius;
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final long mExpiration;
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final PendingIntent mIntent;
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Location mLocation;
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ProximityAlert(int uid, double latitude, double longitude,
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float radius, long expiration, PendingIntent intent) {
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mUid = uid;
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLatitude = latitude;
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLongitude = longitude;
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRadius = radius;
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExpiration = expiration;
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIntent = intent;
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocation = new Location("");
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocation.setLatitude(latitude);
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocation.setLongitude(longitude);
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long getExpiration() {
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mExpiration;
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PendingIntent getIntent() {
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mIntent;
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10832d2078aa1d6e31063f565a20b717f3b8908fff02Yusuf T. Mobile        boolean isInProximity(double latitude, double longitude, float accuracy) {
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Location loc = new Location("");
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            loc.setLatitude(latitude);
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            loc.setLongitude(longitude);
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            double radius = loc.distanceTo(mLocation);
10892d2078aa1d6e31063f565a20b717f3b8908fff02Yusuf T. Mobile            return radius <= Math.max(mRadius,accuracy);
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "ProximityAlert{"
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Integer.toHexString(System.identityHashCode(this))
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " uid " + mUid + mIntent + "}";
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void dump(PrintWriter pw, String prefix) {
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + this);
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mLatitude=" + mLatitude + " mLongitude=" + mLongitude);
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mRadius=" + mRadius + " mExpiration=" + mExpiration);
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mIntent=" + mIntent);
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mLocation:");
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocation.dump(new PrintWriterPrinter(pw), prefix + "  ");
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Listener for receiving locations to trigger proximity alerts
111048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    class ProximityListener extends ILocationListener.Stub implements PendingIntent.OnFinished {
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean isGpsAvailable = false;
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Note: this is called with the lock held.
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onLocationChanged(Location loc) {
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If Gps is available, then ignore updates from NetworkLocationProvider
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (loc.getProvider().equals(LocationManager.GPS_PROVIDER)) {
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                isGpsAvailable = true;
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isGpsAvailable && loc.getProvider().equals(LocationManager.NETWORK_PROVIDER)) {
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Process proximity alerts
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long now = System.currentTimeMillis();
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            double latitude = loc.getLatitude();
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            double longitude = loc.getLongitude();
11292d2078aa1d6e31063f565a20b717f3b8908fff02Yusuf T. Mobile            float accuracy = loc.getAccuracy();
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<PendingIntent> intentsToRemove = null;
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (ProximityAlert alert : mProximityAlerts.values()) {
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PendingIntent intent = alert.getIntent();
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long expiration = alert.getExpiration();
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((expiration == -1) || (now <= expiration)) {
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    boolean entered = mProximitiesEntered.contains(alert);
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    boolean inProximity =
11392d2078aa1d6e31063f565a20b717f3b8908fff02Yusuf T. Mobile                        alert.isInProximity(latitude, longitude, accuracy);
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!entered && inProximity) {
1141105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        if (LOCAL_LOGV) {
1142105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                            Log.v(TAG, "Entered alert");
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mProximitiesEntered.add(alert);
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Intent enteredIntent = new Intent();
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        enteredIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, true);
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        try {
11480528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                            synchronized (this) {
11490528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                                // synchronize to ensure incrementPendingBroadcasts()
115048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // is called before decrementPendingBroadcasts()
115148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                intent.send(mContext, 0, enteredIntent, this, mLocationHandler);
115248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // call this after broadcasting so we do not increment
115348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // if we throw an exeption.
11540528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                                incrementPendingBroadcasts();
115548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            }
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } catch (PendingIntent.CanceledException e) {
1157105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                            if (LOCAL_LOGV) {
1158105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                                Log.v(TAG, "Canceled proximity alert: " + alert, e);
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (intentsToRemove == null) {
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                intentsToRemove = new ArrayList<PendingIntent>();
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            intentsToRemove.add(intent);
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else if (entered && !inProximity) {
1166105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        if (LOCAL_LOGV) {
1167105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                            Log.v(TAG, "Exited alert");
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mProximitiesEntered.remove(alert);
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Intent exitedIntent = new Intent();
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        exitedIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, false);
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        try {
11730528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                            synchronized (this) {
11740528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                                // synchronize to ensure incrementPendingBroadcasts()
117548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // is called before decrementPendingBroadcasts()
117648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                intent.send(mContext, 0, exitedIntent, this, mLocationHandler);
117748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // call this after broadcasting so we do not increment
117848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // if we throw an exeption.
11790528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                                incrementPendingBroadcasts();
118048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            }
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } catch (PendingIntent.CanceledException e) {
1182105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                            if (LOCAL_LOGV) {
1183105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                                Log.v(TAG, "Canceled proximity alert: " + alert, e);
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (intentsToRemove == null) {
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                intentsToRemove = new ArrayList<PendingIntent>();
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            intentsToRemove.add(intent);
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Mark alert for expiration
1193105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    if (LOCAL_LOGV) {
1194105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        Log.v(TAG, "Expiring proximity alert: " + alert);
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (intentsToRemove == null) {
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        intentsToRemove = new ArrayList<PendingIntent>();
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    intentsToRemove.add(alert.getIntent());
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Remove expired alerts
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (intentsToRemove != null) {
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (PendingIntent i : intentsToRemove) {
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mProximityAlerts.remove(i);
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ProximityAlert alert = mProximityAlerts.get(i);
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mProximitiesEntered.remove(alert);
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Note: this is called with the lock held.
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onProviderDisabled(String provider) {
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (provider.equals(LocationManager.GPS_PROVIDER)) {
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                isGpsAvailable = false;
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Note: this is called with the lock held.
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onProviderEnabled(String provider) {
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ignore
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Note: this is called with the lock held.
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onStatusChanged(String provider, int status, Bundle extras) {
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((provider.equals(LocationManager.GPS_PROVIDER)) &&
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (status != LocationProvider.AVAILABLE)) {
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                isGpsAvailable = false;
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
123348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
123448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        public void onSendFinished(PendingIntent pendingIntent, Intent intent,
123548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                int resultCode, String resultData, Bundle resultExtras) {
12360528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            // synchronize to ensure incrementPendingBroadcasts()
12370528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            // is called before decrementPendingBroadcasts()
12380528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            synchronized (this) {
12390528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                decrementPendingBroadcasts();
12400528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
124148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addProximityAlert(double latitude, double longitude,
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float radius, long expiration, PendingIntent intent) {
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
12472f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                addProximityAlertLocked(latitude, longitude, radius, expiration, intent);
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "addProximityAlert got exception:", e);
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void addProximityAlertLocked(double latitude, double longitude,
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float radius, long expiration, PendingIntent intent) {
1259105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
1260105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "addProximityAlert: latitude = " + latitude +
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ", longitude = " + longitude +
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ", expiration = " + expiration +
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ", intent = " + intent);
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Require ability to access all providers for now
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isAllowedProviderSafe(LocationManager.GPS_PROVIDER) ||
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            !isAllowedProviderSafe(LocationManager.NETWORK_PROVIDER)) {
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (expiration != -1) {
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            expiration += System.currentTimeMillis();
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ProximityAlert alert = new ProximityAlert(Binder.getCallingUid(),
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                latitude, longitude, radius, expiration, intent);
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProximityAlerts.put(intent, alert);
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
127948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        if (mProximityReceiver == null) {
128048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            mProximityListener = new ProximityListener();
128148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            mProximityReceiver = new Receiver(mProximityListener);
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
128395427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            for (int i = mProviders.size() - 1; i >= 0; i--) {
128495427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood                LocationProviderProxy provider = mProviders.get(i);
128548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver);
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeProximityAlert(PendingIntent intent) {
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
12922f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               removeProximityAlertLocked(intent);
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "removeProximityAlert got exception:", e);
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void removeProximityAlertLocked(PendingIntent intent) {
1303105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
1304105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "removeProximityAlert: intent = " + intent);
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProximityAlerts.remove(intent);
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mProximityAlerts.size() == 0) {
130948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            removeUpdatesLocked(mProximityReceiver);
131048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            mProximityReceiver = null;
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProximityListener = null;
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     }
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return null if the provider does not exits
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throw SecurityException if the provider is not allowed to be
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * accessed by the caller
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Bundle getProviderInfo(String provider) {
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
13222f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _getProviderInfoLocked(provider);
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "_getProviderInfo got exception:", e);
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Bundle _getProviderInfoLocked(String provider) {
133415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        LocationProviderProxy p = mProvidersByName.get(provider);
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bundle b = new Bundle();
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("network", p.requiresNetwork());
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("satellite", p.requiresSatellite());
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("cell", p.requiresCell());
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("cost", p.hasMonetaryCost());
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("altitude", p.supportsAltitude());
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("speed", p.supportsSpeed());
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("bearing", p.supportsBearing());
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putInt("power", p.getPowerRequirement());
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putInt("accuracy", p.getAccuracy());
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return b;
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isProviderEnabled(String provider) {
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
13572f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _isProviderEnabledLocked(provider);
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "isProviderEnabled got exception:", e);
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1368275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood    public void reportLocation(Location location) {
1369275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
1370275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood                != PackageManager.PERMISSION_GRANTED) {
1371275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood            throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
1372275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        }
1373275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood
13744e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location);
13754e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location);
13764e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        mLocationHandler.sendMessageAtFrontOfQueue(m);
13774e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    }
13784e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean _isProviderEnabledLocked(String provider) {
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
138215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        LocationProviderProxy p = mProvidersByName.get(provider);
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("provider=" + provider);
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return isAllowedBySettingsLocked(provider);
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Location getLastKnownLocation(String provider) {
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
13912f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _getLastKnownLocationLocked(provider);
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "getLastKnownLocation got exception:", e);
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Location _getLastKnownLocationLocked(String provider) {
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
140515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        LocationProviderProxy p = mProvidersByName.get(provider);
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("provider=" + provider);
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isAllowedBySettingsLocked(provider)) {
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14149aa1fa2d3612d1d8ffeae6552d65669f4ca194d9Mike Lockwood        return mLastKnownLocation.get(provider);
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean shouldBroadcastSafe(Location loc, Location lastLoc, UpdateRecord record) {
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Always broadcast the first update
14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (lastLoc == null) {
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Don't broadcast same location again regardless of condition
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO - we should probably still rebroadcast if user explicitly sets a minTime > 0
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (loc.getTime() == lastLoc.getTime()) {
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Check whether sufficient distance has been traveled
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        double minDistance = record.mMinDistance;
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (minDistance > 0.0) {
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (loc.distanceTo(lastLoc) <= minDistance) {
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14404e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    private void handleLocationChangedLocked(Location location) {
14414e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        String provider = location.getProvider();
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (records == null || records.size() == 0) {
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
144715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        LocationProviderProxy p = mProvidersByName.get(provider);
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14524e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        // Update last known location for provider
14534e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        Location lastLocation = mLastKnownLocation.get(provider);
14544e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        if (lastLocation == null) {
14554e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood            mLastKnownLocation.put(provider, new Location(location));
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14574e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood            lastLocation.set(location);
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Fetch latest status update time
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long newStatusUpdateTime = p.getStatusUpdateTime();
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14637ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood       // Get latest status
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bundle extras = new Bundle();
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int status = p.getStatus(extras);
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<Receiver> deadReceivers = null;
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Broadcast location or status to all listeners
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = records.size();
14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0; i<N; i++) {
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            UpdateRecord r = records.get(i);
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Receiver receiver = r.mReceiver;
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14752f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            Location lastLoc = r.mLastFixBroadcast;
14764e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood            if ((lastLoc == null) || shouldBroadcastSafe(location, lastLoc, r)) {
14774e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                if (lastLoc == null) {
14784e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    lastLoc = new Location(location);
14792f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    r.mLastFixBroadcast = lastLoc;
14804e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                } else {
14814e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    lastLoc.set(location);
14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14834e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                if (!receiver.callLocationChangedLocked(location)) {
14844e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    Log.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
14854e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    if (deadReceivers == null) {
14864e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                        deadReceivers = new ArrayList<Receiver>();
14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
14884e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    deadReceivers.add(receiver);
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14922f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            long prevStatusUpdateTime = r.mLastStatusBroadcast;
14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((newStatusUpdateTime > prevStatusUpdateTime) &&
14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14962f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                r.mLastStatusBroadcast = newStatusUpdateTime;
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!receiver.callStatusChangedLocked(provider, status, extras)) {
14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (deadReceivers == null) {
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        deadReceivers = new ArrayList<Receiver>();
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!deadReceivers.contains(receiver)) {
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        deadReceivers.add(receiver);
15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (deadReceivers != null) {
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=deadReceivers.size()-1; i>=0; i--) {
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeUpdatesLocked(deadReceivers.get(i));
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class LocationWorkerHandler extends Handler {
15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void handleMessage(Message msg) {
15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
15214e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                if (msg.what == MESSAGE_LOCATION_CHANGED) {
15224e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    // log("LocationWorkerHandler: MESSAGE_LOCATION_CHANGED!");
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15242f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    synchronized (mLock) {
15254e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                        Location location = (Location) msg.obj;
1526fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                        String provider = location.getProvider();
152798cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood
1528fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                        // notify other providers of the new location
1529fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                        for (int i = mProviders.size() - 1; i >= 0; i--) {
1530fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                            LocationProviderProxy proxy = mProviders.get(i);
1531fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                            if (!provider.equals(proxy.getName())) {
1532fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                                proxy.updateLocation(location);
153398cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood                            }
153498cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood                        }
153598cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood
1536fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                        if (isAllowedBySettingsLocked(provider)) {
1537fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                            handleLocationChangedLocked(location);
15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (Exception e) {
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Log, don't crash!
15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.e(TAG, "Exception in LocationWorkerHandler.handleMessage:", e);
15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15480528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
15490528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        @Override
15500528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        public void onReceive(Context context, Intent intent) {
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String action = intent.getAction();
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15530528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    || action.equals(Intent.ACTION_PACKAGE_RESTARTED)) {
15552f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                synchronized (mLock) {
15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (uid >= 0) {
15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ArrayList<Receiver> removedRecs = null;
15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        for (ArrayList<UpdateRecord> i : mRecordsByProvider.values()) {
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            for (int j=i.size()-1; j>=0; j--) {
15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                UpdateRecord ur = i.get(j);
15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (ur.mReceiver.isPendingIntent() && ur.mUid == uid) {
15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    if (removedRecs == null) {
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        removedRecs = new ArrayList<Receiver>();
15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    }
15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    if (!removedRecs.contains(ur.mReceiver)) {
15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                        removedRecs.add(ur.mReceiver);
15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    }
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ArrayList<ProximityAlert> removedAlerts = null;
15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        for (ProximityAlert i : mProximityAlerts.values()) {
15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (i.mUid == uid) {
15759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (removedAlerts == null) {
15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    removedAlerts = new ArrayList<ProximityAlert>();
15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                if (!removedAlerts.contains(i)) {
15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    removedAlerts.add(i);
15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (removedRecs != null) {
15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            for (int i=removedRecs.size()-1; i>=0; i--) {
15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                removeUpdatesLocked(removedRecs.get(i));
15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (removedAlerts != null) {
15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            for (int i=removedAlerts.size()-1; i>=0; i--) {
15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                removeProximityAlertLocked(removedAlerts.get(i).mIntent);
15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15950528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean noConnectivity =
15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!noConnectivity) {
15994df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    mNetworkState = LocationProvider.AVAILABLE;
16004df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                } else {
16014df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Notify location providers of current network state
16052f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                synchronized (mLock) {
160615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    for (int i = mProviders.size() - 1; i >= 0; i--) {
160715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        LocationProviderProxy provider = mProviders.get(i);
16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (provider.requiresNetwork()) {
16094df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            provider.updateNetworkState(mNetworkState);
16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16150528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    };
16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Wake locks
16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16190528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private void incrementPendingBroadcasts() {
16200528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        synchronized (mWakeLock) {
16210528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (mPendingBroadcasts++ == 0) {
16220528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                try {
16230528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    mWakeLock.acquire();
16240528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    log("Acquired wakelock");
16250528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                } catch (Exception e) {
16260528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // This is to catch a runtime exception thrown when we try to release an
16270528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // already released lock.
16280528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    Log.e(TAG, "exception in acquireWakeLock()", e);
16290528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                }
16300528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
163148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
163248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
163348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
163448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private void decrementPendingBroadcasts() {
16350528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        synchronized (mWakeLock) {
163648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (--mPendingBroadcasts == 0) {
16370528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                try {
16380528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // Release wake lock
16390528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    if (mWakeLock.isHeld()) {
16400528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                        mWakeLock.release();
16410528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                        log("Released wakelock");
16420528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    } else {
16430528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                        log("Can't release wakelock again!");
16440528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    }
16450528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                } catch (Exception e) {
16460528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // This is to catch a runtime exception thrown when we try to release an
16470528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // already released lock.
16480528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    Log.e(TAG, "exception in releaseWakeLock()", e);
16490528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                }
165048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
165148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
165248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
165348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Geocoder
16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String getFromLocation(double latitude, double longitude, int maxResults,
1657a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            String language, String country, String variant, String appName, List<Address> addrs) {
1658a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        if (mGeocodeProvider != null) {
1659a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            try {
1660a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood                return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, language, country,
1661a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood                        variant, appName,  addrs);
1662a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            } catch (RemoteException e) {
1663a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood                Log.e(TAG, "getFromLocation failed", e);
16643681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood                mGeocodeProvider = null;
16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1667a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        return null;
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1670a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood
16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String getFromLocationName(String locationName,
1672a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            double lowerLeftLatitude, double lowerLeftLongitude,
1673a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            double upperRightLatitude, double upperRightLongitude, int maxResults,
1674a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            String language, String country, String variant, String appName, List<Address> addrs) {
1675a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood
1676a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        if (mGeocodeProvider != null) {
1677a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            try {
1678a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood                return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
1679a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood                        lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
1680a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood                        maxResults, language, country, variant, appName, addrs);
1681a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            } catch (RemoteException e) {
1682a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood                Log.e(TAG, "getFromLocationName failed", e);
16833681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood                mGeocodeProvider = null;
16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1686a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        return null;
16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Mock Providers
16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void checkMockPermissionsSafe() {
16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(),
16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1;
16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!allowMocks) {
16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting");
16969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) !=
16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PackageManager.PERMISSION_GRANTED) {
17009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission");
17019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite,
17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17092f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
17104e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood            MockProvider provider = new MockProvider(name, this,
17114e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                requiresNetwork, requiresSatellite,
17129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                requiresCell, hasMonetaryCost, supportsAltitude,
17139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                supportsSpeed, supportsBearing, powerRequirement, accuracy);
17147566c1debebe072af76411e11d96810fd1409482Mike Lockwood            // remove the real provider if we are replacing GPS or network provider
17157566c1debebe072af76411e11d96810fd1409482Mike Lockwood            if (LocationManager.GPS_PROVIDER.equals(name)
17167566c1debebe072af76411e11d96810fd1409482Mike Lockwood                    || LocationManager.NETWORK_PROVIDER.equals(name)) {
17177566c1debebe072af76411e11d96810fd1409482Mike Lockwood                LocationProviderProxy proxy = mProvidersByName.get(name);
17187566c1debebe072af76411e11d96810fd1409482Mike Lockwood                if (proxy != null) {
17197566c1debebe072af76411e11d96810fd1409482Mike Lockwood                    proxy.enableLocationTracking(false);
17207566c1debebe072af76411e11d96810fd1409482Mike Lockwood                    removeProvider(proxy);
17217566c1debebe072af76411e11d96810fd1409482Mike Lockwood                }
17227566c1debebe072af76411e11d96810fd1409482Mike Lockwood            }
172315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (mProvidersByName.get(name) != null) {
17249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
17259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
172615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            addProvider(new LocationProviderProxy(name, provider));
17277ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mMockProviders.put(name, provider);
17287566c1debebe072af76411e11d96810fd1409482Mike Lockwood            mLastKnownLocation.put(name, null);
17299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeTestProvider(String provider) {
17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17352f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
17367ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
17377ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
17389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
17399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
174015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            removeProvider(mProvidersByName.get(provider));
17417ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mMockProviders.remove(mockProvider);
17427566c1debebe072af76411e11d96810fd1409482Mike Lockwood            // reinstall real provider if we were mocking GPS or network provider
17437566c1debebe072af76411e11d96810fd1409482Mike Lockwood            if (LocationManager.GPS_PROVIDER.equals(provider) &&
17447566c1debebe072af76411e11d96810fd1409482Mike Lockwood                    mGpsLocationProvider != null) {
17457566c1debebe072af76411e11d96810fd1409482Mike Lockwood                addProvider(mGpsLocationProvider);
17467566c1debebe072af76411e11d96810fd1409482Mike Lockwood            } else if (LocationManager.NETWORK_PROVIDER.equals(provider) &&
17477566c1debebe072af76411e11d96810fd1409482Mike Lockwood                    mNetworkLocationProvider != null) {
17487566c1debebe072af76411e11d96810fd1409482Mike Lockwood                addProvider(mNetworkLocationProvider);
17497566c1debebe072af76411e11d96810fd1409482Mike Lockwood            }
17507566c1debebe072af76411e11d96810fd1409482Mike Lockwood            mLastKnownLocation.put(provider, null);
17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderLocation(String provider, Location loc) {
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17572f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
17587ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
17597ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
176295427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
176395427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            long identity = Binder.clearCallingIdentity();
17647ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.setLocation(loc);
176595427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            Binder.restoreCallingIdentity(identity);
17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderLocation(String provider) {
17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17712f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
17727ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
17737ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17767ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.clearLocation();
17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderEnabled(String provider, boolean enabled) {
17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17822f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
17837ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
17847ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (enabled) {
17887ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                mockProvider.enable();
17899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEnabledProviders.add(provider);
17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDisabledProviders.remove(provider);
17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
17927ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                mockProvider.disable();
17939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEnabledProviders.remove(provider);
17949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDisabledProviders.add(provider);
17959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderEnabled(String provider) {
18019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18022f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18037ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18047ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEnabledProviders.remove(provider);
18089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDisabledProviders.remove(provider);
18099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
18109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
18149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18152f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18167ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18177ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18207ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.setStatus(status, extras, updateTime);
18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderStatus(String provider) {
18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18262f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18277ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18287ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18317ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.clearStatus();
18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void log(String log) {
18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Log.isLoggable(TAG, Log.VERBOSE)) {
18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.d(TAG, log);
18389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
18429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
18440528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            pw.println("Permission Denial: can't dump LocationManagerService from from pid="
18459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Binder.getCallingPid()
18469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", uid=" + Binder.getCallingUid());
18479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
18489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18502f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("Current Location Manager state:");
18529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  sProvidersLoaded=" + sProvidersLoaded);
18539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Listeners:");
18542f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            int N = mReceivers.size();
18559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
18562f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                pw.println("    " + mReceivers.get(i));
18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Location Listeners:");
18592f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            for (Receiver i : mReceivers.values()) {
18602f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                pw.println("    " + i + ":");
18612f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                for (Map.Entry<String,UpdateRecord> j : i.mUpdateRecords.entrySet()) {
18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("      " + j.getKey() + ":");
18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    j.getValue().dump(pw, "        ");
18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
18659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Records by Provider:");
18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (Map.Entry<String, ArrayList<UpdateRecord>> i
18689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    : mRecordsByProvider.entrySet()) {
18699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("    " + i.getKey() + ":");
18709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (UpdateRecord j : i.getValue()) {
18719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("      " + j + ":");
18729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    j.dump(pw, "        ");
18739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
18749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Last Known Locations:");
18769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (Map.Entry<String, Location> i
18779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    : mLastKnownLocation.entrySet()) {
18789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("    " + i.getKey() + ":");
18799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                i.getValue().dump(new PrintWriterPrinter(pw), "      ");
18809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mProximityAlerts.size() > 0) {
18829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Proximity Alerts:");
18839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (Map.Entry<PendingIntent, ProximityAlert> i
18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        : mProximityAlerts.entrySet()) {
18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i.getKey() + ":");
18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    i.getValue().dump(pw, "      ");
18879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
18889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mProximitiesEntered.size() > 0) {
18909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Proximities Entered:");
18919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (ProximityAlert i : mProximitiesEntered) {
18929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i + ":");
18939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    i.dump(pw, "      ");
18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
189648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            pw.println("  mProximityReceiver=" + mProximityReceiver);
18979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  mProximityListener=" + mProximityListener);
18989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mEnabledProviders.size() > 0) {
18999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Enabled Providers:");
19009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (String i : mEnabledProviders) {
19019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i);
19029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mDisabledProviders.size() > 0) {
19069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Disabled Providers:");
19079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (String i : mDisabledProviders) {
19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i);
19099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mMockProviders.size() > 0) {
19139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Mock Providers:");
19149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
19157ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                    i.getValue().dump(pw, "      ");
19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1921