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
3021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport android.app.Activity;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.PendingIntent;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver;
33628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwoodimport android.content.ComponentName;
349637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwoodimport android.content.ContentQueryMap;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter;
39628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwoodimport android.content.ServiceConnection;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
41628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwoodimport android.content.res.Resources;
429637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwoodimport android.database.Cursor;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Address;
4434901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwoodimport android.location.GeocoderParams;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.IGpsStatusListener;
4615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwoodimport android.location.IGpsStatusProvider;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.ILocationListener;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.ILocationManager;
4922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport android.location.INetInitiatedListener;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Location;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationManager;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationProvider;
53d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwoodimport android.location.LocationProviderInterface;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.ConnectivityManager;
5503d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwoodimport android.net.NetworkInfo;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
613d12b51ee38537f6760a833618948f936e75561dMike Lockwoodimport android.os.Looper;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager;
64e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwoodimport android.os.Process;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
688a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.PrintWriterPrinter;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
71628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwoodimport com.android.internal.location.GeocoderProxy;
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.location.GpsLocationProvider;
73628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwoodimport com.android.internal.location.GpsNetInitiatedHandler;
74e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwoodimport com.android.internal.location.LocationProviderProxy;
757ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwoodimport com.android.internal.location.MockProvider;
76a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwoodimport com.android.internal.location.PassiveProvider;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The service class that manages LocationProviders and issues location
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * updates and alerts.
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
843d12b51ee38537f6760a833618948f936e75561dMike Lockwoodpublic class LocationManagerService extends ILocationManager.Stub implements Runnable {
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "LocationManagerService";
86105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final boolean LOCAL_LOGV = false;
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // The last time a location was written, by provider name.
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<String,Long> mLastWriteTime = new HashMap<String,Long>();
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_FINE_LOCATION =
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        android.Manifest.permission.ACCESS_FINE_LOCATION;
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_COARSE_LOCATION =
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        android.Manifest.permission.ACCESS_COARSE_LOCATION;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_MOCK_LOCATION =
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        android.Manifest.permission.ACCESS_MOCK_LOCATION;
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
99275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood    private static final String INSTALL_LOCATION_PROVIDER =
100275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Set of providers that are explicitly enabled
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Set<String> mEnabledProviders = new HashSet<String>();
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Set of providers that are explicitly disabled
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Set<String> mDisabledProviders = new HashSet<String>();
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Locations, status values, and extras for mock providers
1097ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood    private final HashMap<String,MockProvider> mMockProviders = new HashMap<String,MockProvider>();
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean sProvidersLoaded = false;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Context mContext;
114628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood    private GeocoderProxy mGeocodeProvider;
11515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private IGpsStatusProvider mGpsStatusProvider;
11622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private INetInitiatedListener mNetInitiatedListener;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private LocationWorkerHandler mLocationHandler;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1197566c1debebe072af76411e11d96810fd1409482Mike Lockwood    // Cache the real providers for use in addTestProvider() and removeTestProvider()
120d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood     LocationProviderInterface mNetworkLocationProvider;
121d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood     LocationProviderInterface mGpsLocationProvider;
1227566c1debebe072af76411e11d96810fd1409482Mike Lockwood
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Handler messages
1244e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    private static final int MESSAGE_LOCATION_CHANGED = 1;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1260528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    // wakelock variables
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final static String WAKELOCK_KEY = "LocationManagerService";
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private PowerManager.WakeLock mWakeLock = null;
12948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private int mPendingBroadcasts;
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1322f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood     * List of all receivers.
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1342f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final HashMap<Object, Receiver> mReceivers = new HashMap<Object, Receiver>();
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
13715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    /**
13815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood     * List of location providers.
13915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood     */
140d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    private final ArrayList<LocationProviderInterface> mProviders =
141d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        new ArrayList<LocationProviderInterface>();
142d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    private final HashMap<String, LocationProviderInterface> mProvidersByName
143d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        = new HashMap<String, LocationProviderInterface>();
14415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1462f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood     * Object used internally for synchronization
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1482f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final Object mLock = new Object();
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Mapping from provider name to all its UpdateRecords
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashMap<String,ArrayList<UpdateRecord>> mRecordsByProvider =
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashMap<String,ArrayList<UpdateRecord>>();
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Proximity listeners
15748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private Receiver mProximityReceiver = null;
15848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private ILocationListener mProximityListener = null;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<PendingIntent,ProximityAlert> mProximityAlerts =
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashMap<PendingIntent,ProximityAlert>();
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashSet<ProximityAlert> mProximitiesEntered =
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashSet<ProximityAlert>();
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Last known location for each provider
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<String,Location> mLastKnownLocation =
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashMap<String,Location>();
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1684df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    private int mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
1694df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
1709637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood    // for Settings change notification
1719637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood    private ContentQueryMap mSettings;
1729637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A wrapper class holding either an ILocationListener or a PendingIntent to receive
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * location updates.
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ILocationListener mListener;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final PendingIntent mPendingIntent;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Object mKey;
1812f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
18248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        int mPendingBroadcasts;
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1842f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver(ILocationListener listener) {
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = listener;
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPendingIntent = null;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mKey = listener.asBinder();
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1902f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver(PendingIntent intent) {
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPendingIntent = intent;
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = null;
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mKey = intent;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean equals(Object otherObj) {
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (otherObj instanceof Receiver) {
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mKey.equals(
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((Receiver)otherObj).mKey);
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int hashCode() {
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mKey.hashCode();
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2093681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return "Receiver{"
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + Integer.toHexString(System.identityHashCode(this))
2152f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                        + " Listener " + mKey + "}";
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return "Receiver{"
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + Integer.toHexString(System.identityHashCode(this))
2192f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                        + " Intent " + mKey + "}";
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean isListener() {
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mListener != null;
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean isPendingIntent() {
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mPendingIntent != null;
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ILocationListener getListener() {
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mListener;
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("Request for non-existent listener");
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public PendingIntent getPendingIntent() {
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mPendingIntent != null) {
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mPendingIntent;
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("Request for non-existent intent");
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
24848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
24948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
25048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
25148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mListener.onStatusChanged(provider, status, extras);
25248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (mListener != mProximityListener) {
25348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // call this after broadcasting so we do not increment
25448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // if we throw an exeption.
25548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            incrementPendingBroadcastsLocked();
25648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
25748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent statusChanged = new Intent();
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                statusChanged.putExtras(extras);
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
26648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
26748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
26848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
26948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler);
27048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
27148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
27248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
27348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (PendingIntent.CanceledException e) {
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean callLocationChangedLocked(Location location) {
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
28448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
28548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
28648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
28748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mListener.onLocationChanged(location);
28848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (mListener != mProximityListener) {
28948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // call this after broadcasting so we do not increment
29048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // if we throw an exeption.
29148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            incrementPendingBroadcastsLocked();
29248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
29348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent locationChanged = new Intent();
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, location);
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
30148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
30248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
30348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
30448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler);
30548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
30648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
30748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
30848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
30948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                } catch (PendingIntent.CanceledException e) {
31048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    return false;
31148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
31248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
31348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            return true;
31448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
31548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
31648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        public boolean callProviderEnabledLocked(String provider, boolean enabled) {
31748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (mListener != null) {
31848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                try {
31948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
32048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
32148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
32248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (enabled) {
32348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            mListener.onProviderEnabled(provider);
32448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        } else {
32548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            mListener.onProviderDisabled(provider);
32648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
32748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (mListener != mProximityListener) {
32848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // call this after broadcasting so we do not increment
32948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // if we throw an exeption.
33048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            incrementPendingBroadcastsLocked();
33148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
33248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
33348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                } catch (RemoteException e) {
33448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    return false;
33548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
33648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            } else {
33748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                Intent providerIntent = new Intent();
33848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
33948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                try {
34048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
34148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
34248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
34348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler);
34448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
34548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
34648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
34748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (PendingIntent.CanceledException e) {
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
356105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            if (LOCAL_LOGV) {
3578a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.v(TAG, "Location listener died");
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3592f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeUpdatesLocked(this);
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
36248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            synchronized (this) {
36348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                if (mPendingBroadcasts > 0) {
36448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    LocationManagerService.this.decrementPendingBroadcasts();
36548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    mPendingBroadcasts = 0;
36648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
36748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
36848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
36948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
37048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        public void onSendFinished(PendingIntent pendingIntent, Intent intent,
37148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                int resultCode, String resultData, Bundle resultExtras) {
3720528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            synchronized (this) {
3730528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                decrementPendingBroadcastsLocked();
3740528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
37548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
37648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
3770528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // this must be called while synchronized by caller in a synchronized block
37848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        // containing the sending of the broadcaset
37948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        private void incrementPendingBroadcastsLocked() {
38048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (mPendingBroadcasts++ == 0) {
3810528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                LocationManagerService.this.incrementPendingBroadcasts();
38248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
38348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
38448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
3850528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        private void decrementPendingBroadcastsLocked() {
3860528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (--mPendingBroadcasts == 0) {
3870528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                LocationManagerService.this.decrementPendingBroadcasts();
38848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
38948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
39048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
39148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
39248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    public void locationCallbackFinished(ILocationListener listener) {
393080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //Do not use getReceiver here as that will add the ILocationListener to
394080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //the receiver list if it is not found.  If it is not found then the
395080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //LocationListener was removed when it had a pending broadcast and should
396080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //not be added back.
397080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        IBinder binder = listener.asBinder();
398080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        Receiver receiver = mReceivers.get(binder);
39948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        if (receiver != null) {
4000528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            synchronized (receiver) {
4010528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                // so wakelock calls will succeed
4020528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                long identity = Binder.clearCallingIdentity();
4030528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                receiver.decrementPendingBroadcastsLocked();
4040528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                Binder.restoreCallingIdentity(identity);
4050528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood           }
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4099637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood    private final class SettingsObserver implements Observer {
4109637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        public void update(Observable o, Object arg) {
4112f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
4129637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood                updateProvidersLocked();
4139637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood            }
4149637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        }
4159637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood    }
4169637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood
417d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    private void addProvider(LocationProviderInterface provider) {
41815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProviders.add(provider);
41915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProvidersByName.put(provider.getName(), provider);
42015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
42115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
422d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    private void removeProvider(LocationProviderInterface provider) {
42315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProviders.remove(provider);
42415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProvidersByName.remove(provider.getName());
42515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
42615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void loadProviders() {
4282f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sProvidersLoaded) {
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Load providers
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            loadProvidersLocked();
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sProvidersLoaded = true;
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void loadProvidersLocked() {
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            _loadProvidersLocked();
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
4438a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "Exception loading providers:", e);
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void _loadProvidersLocked() {
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Attempt to load "real" providers first
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (GpsLocationProvider.isSupported()) {
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Create a gps location provider
451d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);
452d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
453d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
454d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            addProvider(gpsProvider);
455d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            mGpsLocationProvider = gpsProvider;
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
458a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        // create a passive location provider, which is always enabled
459a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        PassiveProvider passiveProvider = new PassiveProvider(this);
460a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        addProvider(passiveProvider);
461a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        mEnabledProviders.add(passiveProvider.getName());
462a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood
463628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood        // initialize external network location and geocoder services
464628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood        Resources resources = mContext.getResources();
465628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood        String serviceName = resources.getString(
466628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                com.android.internal.R.string.config_networkLocationProvider);
467628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood        if (serviceName != null) {
468628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood            mNetworkLocationProvider =
469628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                new LocationProviderProxy(mContext, LocationManager.NETWORK_PROVIDER,
470628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                        serviceName, mLocationHandler);
471628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood            addProvider(mNetworkLocationProvider);
472628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood        }
473628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood
474628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood        serviceName = resources.getString(com.android.internal.R.string.config_geocodeProvider);
475628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood        if (serviceName != null) {
476628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood            mGeocodeProvider = new GeocoderProxy(mContext, serviceName);
477628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood        }
478628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateProvidersLocked();
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context the context that the LocationManagerService runs in
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public LocationManagerService(Context context) {
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super();
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
4883d12b51ee38537f6760a833618948f936e75561dMike Lockwood
489105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
4908a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.v(TAG, "Constructed LocationManager Service");
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4923d12b51ee38537f6760a833618948f936e75561dMike Lockwood    }
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
49446db504de583d7d644a28a4e7adae43eed5df1baMike Lockwood    void systemReady() {
49546db504de583d7d644a28a4e7adae43eed5df1baMike Lockwood        // we defer starting up the service until the system is ready
49646db504de583d7d644a28a4e7adae43eed5df1baMike Lockwood        Thread thread = new Thread(null, this, "LocationManagerService");
49746db504de583d7d644a28a4e7adae43eed5df1baMike Lockwood        thread.start();
49846db504de583d7d644a28a4e7adae43eed5df1baMike Lockwood    }
49946db504de583d7d644a28a4e7adae43eed5df1baMike Lockwood
5003d12b51ee38537f6760a833618948f936e75561dMike Lockwood    private void initialize() {
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Create a wake lock, needs to be done before calling loadProviders() below
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
5040528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Load providers
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        loadProviders();
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Register for Network (Wifi or Mobile) updates
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IntentFilter intentFilter = new IntentFilter();
5100528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
5110528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // Register for Package Manager updates
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
51421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        intentFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
5150528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        mContext.registerReceiver(mBroadcastReceiver, intentFilter);
516b56ae20b22fd7283df32072a431ab6d4965f3c1bSuchi Amalapurapu        IntentFilter sdFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
51708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu        mContext.registerReceiver(mBroadcastReceiver, sdFilter);
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5199637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        // listen for settings changes
5209637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        ContentResolver resolver = mContext.getContentResolver();
5219637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        Cursor settingsCursor = resolver.query(Settings.Secure.CONTENT_URI, null,
5229637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood                "(" + Settings.System.NAME + "=?)",
5239637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood                new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
5249637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood                null);
5259637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mLocationHandler);
5269637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        SettingsObserver settingsObserver = new SettingsObserver();
5279637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        mSettings.addObserver(settingsObserver);
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5303d12b51ee38537f6760a833618948f936e75561dMike Lockwood    public void run()
5313d12b51ee38537f6760a833618948f936e75561dMike Lockwood    {
5323d12b51ee38537f6760a833618948f936e75561dMike Lockwood        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
5333d12b51ee38537f6760a833618948f936e75561dMike Lockwood        Looper.prepare();
5343d12b51ee38537f6760a833618948f936e75561dMike Lockwood        mLocationHandler = new LocationWorkerHandler();
5353d12b51ee38537f6760a833618948f936e75561dMike Lockwood        initialize();
5363d12b51ee38537f6760a833618948f936e75561dMike Lockwood        Looper.loop();
5373d12b51ee38537f6760a833618948f936e75561dMike Lockwood    }
5383d12b51ee38537f6760a833618948f936e75561dMike Lockwood
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean isAllowedBySettingsLocked(String provider) {
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabledProviders.contains(provider)) {
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDisabledProviders.contains(provider)) {
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Use system settings
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ContentResolver resolver = mContext.getContentResolver();
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5498eb3ea659761edc2cd5db3acf448059f19389e5eBrad Larson        return Settings.Secure.isLocationProviderEnabled(resolver, provider);
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void checkPermissionsSafe(String provider) {
553a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        if ((LocationManager.GPS_PROVIDER.equals(provider)
554a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                 || LocationManager.PASSIVE_PROVIDER.equals(provider))
555b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (LocationManager.NETWORK_PROVIDER.equals(provider)
560b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)
562b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION)
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException(
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "Requires ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission");
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean isAllowedProviderSafe(String provider) {
57043cc4696bfa7c3839931f3360c9660a9e41050b3Bryan Mawhinney        if ((LocationManager.GPS_PROVIDER.equals(provider)
57143cc4696bfa7c3839931f3360c9660a9e41050b3Bryan Mawhinney                || LocationManager.PASSIVE_PROVIDER.equals(provider))
572b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (LocationManager.NETWORK_PROVIDER.equals(provider)
577b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)
579b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION)
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<String> getAllProviders() {
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
5892f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _getAllProvidersLocked();
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
5958a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "getAllProviders got exception:", e);
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private List<String> _getAllProvidersLocked() {
601105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
6028a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.v(TAG, "getAllProviders");
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
60415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        ArrayList<String> out = new ArrayList<String>(mProviders.size());
60515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        for (int i = mProviders.size() - 1; i >= 0; i--) {
606d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            LocationProviderInterface p = mProviders.get(i);
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            out.add(p.getName());
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return out;
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<String> getProviders(boolean enabledOnly) {
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
6142f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _getProvidersLocked(enabledOnly);
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
6208a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "getProviders got exception:", e);
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private List<String> _getProvidersLocked(boolean enabledOnly) {
626105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
6278a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.v(TAG, "getProviders");
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
62915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        ArrayList<String> out = new ArrayList<String>(mProviders.size());
63015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        for (int i = mProviders.size() - 1; i >= 0; i--) {
631d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            LocationProviderInterface p = mProviders.get(i);
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = p.getName();
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isAllowedProviderSafe(name)) {
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (enabledOnly && !isAllowedBySettingsLocked(name)) {
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                out.add(name);
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return out;
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateProvidersLocked() {
64415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        for (int i = mProviders.size() - 1; i >= 0; i--) {
645d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            LocationProviderInterface p = mProviders.get(i);
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean isEnabled = p.isEnabled();
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = p.getName();
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isEnabled && !shouldBeEnabled) {
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                updateProviderListenersLocked(name, false);
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (!isEnabled && shouldBeEnabled) {
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                updateProviderListenersLocked(name, true);
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateProviderListenersLocked(String provider, boolean enabled) {
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int listeners = 0;
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
662d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<Receiver> deadReceivers = null;
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (records != null) {
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int N = records.size();
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                UpdateRecord record = records.get(i);
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Sends a notification message to the receiver
67548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
67648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    if (deadReceivers == null) {
67748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        deadReceivers = new ArrayList<Receiver>();
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6794686657cee6411eb00235d49b4a8663a96361a00Simon Schoar                    deadReceivers.add(record.mReceiver);
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listeners++;
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (deadReceivers != null) {
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=deadReceivers.size()-1; i>=0; i--) {
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeUpdatesLocked(deadReceivers.get(i));
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (enabled) {
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.enable();
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (listeners > 0) {
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.setMinTime(getMinTimeLocked(provider));
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.enableLocationTracking(true);
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.enableLocationTracking(false);
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.disable();
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long getMinTimeLocked(String provider) {
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long minTime = Long.MAX_VALUE;
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (records != null) {
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=records.size()-1; i>=0; i--) {
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                minTime = Math.min(minTime, records.get(i).mMinTime);
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return minTime;
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class UpdateRecord {
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String mProvider;
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Receiver mReceiver;
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final long mMinTime;
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float mMinDistance;
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int mUid;
7202f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Location mLastFixBroadcast;
7212f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        long mLastStatusBroadcast;
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Note: must be constructed with lock held.
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        UpdateRecord(String provider, long minTime, float minDistance,
7272f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            Receiver receiver, int uid) {
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProvider = provider;
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mReceiver = receiver;
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMinTime = minTime;
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMinDistance = minDistance;
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mUid = uid;
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (records == null) {
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                records = new ArrayList<UpdateRecord>();
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRecordsByProvider.put(provider, records);
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!records.contains(this)) {
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                records.add(this);
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Method to be called when a record will no longer be used.  Calling this multiple times
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * must have the same effect as calling it once.
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void disposeLocked() {
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<UpdateRecord> records = mRecordsByProvider.get(this.mProvider);
7503a76fd627945c1df59aa0318867401e0e53da022Mike Lockwood            if (records != null) {
7513a76fd627945c1df59aa0318867401e0e53da022Mike Lockwood                records.remove(this);
7523a76fd627945c1df59aa0318867401e0e53da022Mike Lockwood            }
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "UpdateRecord{"
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Integer.toHexString(System.identityHashCode(this))
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " " + mProvider + " " + mReceiver + "}";
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void dump(PrintWriter pw, String prefix) {
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + this);
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mProvider=" + mProvider + " mReceiver=" + mReceiver);
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mMinTime=" + mMinTime + " mMinDistance=" + mMinDistance);
7662f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            pw.println(prefix + "mUid=" + mUid);
7672f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            pw.println(prefix + "mLastFixBroadcast:");
7683c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger            if (mLastFixBroadcast != null) {
7693c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger                mLastFixBroadcast.dump(new PrintWriterPrinter(pw), prefix + "  ");
7703c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger            }
7712f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            pw.println(prefix + "mLastStatusBroadcast=" + mLastStatusBroadcast);
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7752f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private Receiver getReceiver(ILocationListener listener) {
7762f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        IBinder binder = listener.asBinder();
7772f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver receiver = mReceivers.get(binder);
7782f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (receiver == null) {
7792f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            receiver = new Receiver(listener);
7802f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            mReceivers.put(binder, receiver);
7812f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
7822f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            try {
7832f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                if (receiver.isListener()) {
7842f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    receiver.getListener().asBinder().linkToDeath(receiver, 0);
7852f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                }
7862f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            } catch (RemoteException e) {
7878a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.e(TAG, "linkToDeath failed:", e);
7882f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                return null;
7892f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
7902f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
7912f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        return receiver;
7922f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
7932f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
7942f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private Receiver getReceiver(PendingIntent intent) {
7952f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver receiver = mReceivers.get(intent);
7962f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (receiver == null) {
7972f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            receiver = new Receiver(intent);
7982f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            mReceivers.put(intent, receiver);
7992f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
8002f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        return receiver;
8012f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
8022f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8032f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private boolean providerHasListener(String provider, int uid, Receiver excludedReceiver) {
8042f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
8052f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (records != null) {
8062f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            for (int i = records.size() - 1; i >= 0; i--) {
8072f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                UpdateRecord record = records.get(i);
8082f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                if (record.mUid == uid && record.mReceiver != excludedReceiver) {
8092f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    return true;
8102f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                }
8112f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood           }
8122f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
81395427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood        for (ProximityAlert alert : mProximityAlerts.values()) {
81495427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            if (alert.mUid == uid) {
81595427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood                return true;
8162f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
8172f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
8182f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        return false;
8192f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
8202f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void requestLocationUpdates(String provider,
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long minTime, float minDistance, ILocationListener listener) {
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8252f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
8262f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                requestLocationUpdatesLocked(provider, minTime, minDistance, getReceiver(listener));
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
8303b9ef08bbbdc95a609fa7883d6fff4b4fd22e33cMike Lockwood        } catch (IllegalArgumentException iae) {
8313b9ef08bbbdc95a609fa7883d6fff4b4fd22e33cMike Lockwood            throw iae;
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
8338a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "requestUpdates got exception:", e);
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void requestLocationUpdatesPI(String provider,
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long minTime, float minDistance, PendingIntent intent) {
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8402f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
8412f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                requestLocationUpdatesLocked(provider, minTime, minDistance, getReceiver(intent));
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
8453b9ef08bbbdc95a609fa7883d6fff4b4fd22e33cMike Lockwood        } catch (IllegalArgumentException iae) {
8463b9ef08bbbdc95a609fa7883d6fff4b4fd22e33cMike Lockwood            throw iae;
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
8488a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.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) {
8558a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.v(TAG, "_requestLocationUpdates: listener = " + receiver);
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
858d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
859d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        if (p == 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) {
877d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                p.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);
883d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                p.setMinTime(minTimeForProvider);
884d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                p.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;
9013b9ef08bbbdc95a609fa7883d6fff4b4fd22e33cMike Lockwood        } catch (IllegalArgumentException iae) {
9023b9ef08bbbdc95a609fa7883d6fff4b4fd22e33cMike Lockwood            throw iae;
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
9048a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "removeUpdates got exception:", e);
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeUpdatesPI(PendingIntent intent) {
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
9102f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
9112f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                removeUpdatesLocked(getReceiver(intent));
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
9153b9ef08bbbdc95a609fa7883d6fff4b4fd22e33cMike Lockwood        } catch (IllegalArgumentException iae) {
9163b9ef08bbbdc95a609fa7883d6fff4b4fd22e33cMike Lockwood            throw iae;
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
9188a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "removeUpdates got exception:", e);
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void removeUpdatesLocked(Receiver receiver) {
923105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
9248a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.v(TAG, "_removeUpdates: listener = " + receiver);
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // so wakelock calls will succeed
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int callingUid = Binder.getCallingUid();
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identity = Binder.clearCallingIdentity();
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
9312f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
9322f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
933080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                synchronized(receiver) {
934080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                    if(receiver.mPendingBroadcasts > 0) {
935080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                        decrementPendingBroadcasts();
936080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                        receiver.mPendingBroadcasts = 0;
937080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                    }
938080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                }
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Record which providers were associated with this listener
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            HashSet<String> providers = new HashSet<String>();
9432f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            HashMap<String,UpdateRecord> oldRecords = receiver.mUpdateRecords;
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (oldRecords != null) {
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Call dispose() on the obsolete update records.
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (UpdateRecord record : oldRecords.values()) {
9472f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    if (!providerHasListener(record.mProvider, callingUid, receiver)) {
948d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                        LocationProviderInterface p = mProvidersByName.get(record.mProvider);
949d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                        if (p != null) {
950d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                            p.removeListener(callingUid);
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    record.disposeLocked();
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Accumulate providers
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                providers.addAll(oldRecords.keySet());
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // See if the providers associated with this listener have any
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // other listeners; if one does, inform it of the new smallest minTime
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // value; if one does not, disable location tracking for it
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (String provider : providers) {
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // If provider is already disabled, don't need to do anything
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!isAllowedBySettingsLocked(provider)) {
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean hasOtherListener = false;
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ArrayList<UpdateRecord> recordsForProvider = mRecordsByProvider.get(provider);
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (recordsForProvider != null && recordsForProvider.size() > 0) {
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    hasOtherListener = true;
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
974d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                LocationProviderInterface p = mProvidersByName.get(provider);
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (p != null) {
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (hasOtherListener) {
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        p.setMinTime(getMinTimeLocked(provider));
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        p.enableLocationTracking(false);
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(identity);
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean addGpsStatusListener(IGpsStatusListener listener) {
98915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mGpsStatusProvider == null) {
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
992b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood        if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) !=
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PackageManager.PERMISSION_GRANTED) {
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
99815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            mGpsStatusProvider.addGpsStatusListener(listener);
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
10008a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "mGpsStatusProvider.addGpsStatusListener failed", e);
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeGpsStatusListener(IGpsStatusListener listener) {
10072f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
100815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            try {
100915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                mGpsStatusProvider.removeGpsStatusListener(listener);
101015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            } catch (Exception e) {
10118a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.e(TAG, "mGpsStatusProvider.removeGpsStatusListener failed", e);
101215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendExtraCommand(String provider, String command, Bundle extras) {
1017c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood        if (provider == null) {
1018c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood            // throw NullPointerException to remain compatible with previous implementation
1019c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood            throw new NullPointerException();
1020c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood        }
1021c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // first check for permission to the provider
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // and check for ACCESS_LOCATION_EXTRA_COMMANDS
1025b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood        if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10302f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
1031d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            LocationProviderInterface p = mProvidersByName.get(provider);
1032d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            if (p == null) {
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1036d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            return p.sendExtraCommand(command, extras);
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
104022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    public boolean sendNiResponse(int notifId, int userResponse)
104122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    {
104218ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood        if (Binder.getCallingUid() != Process.myUid()) {
104318ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood            throw new SecurityException(
104418ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood                    "calling sendNiResponse from outside of the system is not allowed");
104518ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood        }
104622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        try {
104722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
104822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        }
104922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        catch (RemoteException e)
105022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        {
10518a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
105222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            return false;
105322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        }
105422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    }
105522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class ProximityAlert {
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int  mUid;
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final double mLatitude;
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final double mLongitude;
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float mRadius;
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final long mExpiration;
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final PendingIntent mIntent;
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Location mLocation;
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ProximityAlert(int uid, double latitude, double longitude,
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float radius, long expiration, PendingIntent intent) {
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mUid = uid;
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLatitude = latitude;
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLongitude = longitude;
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRadius = radius;
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExpiration = expiration;
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIntent = intent;
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocation = new Location("");
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocation.setLatitude(latitude);
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocation.setLongitude(longitude);
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long getExpiration() {
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mExpiration;
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PendingIntent getIntent() {
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mIntent;
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10872d2078aa1d6e31063f565a20b717f3b8908fff02Yusuf T. Mobile        boolean isInProximity(double latitude, double longitude, float accuracy) {
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Location loc = new Location("");
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            loc.setLatitude(latitude);
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            loc.setLongitude(longitude);
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            double radius = loc.distanceTo(mLocation);
10932d2078aa1d6e31063f565a20b717f3b8908fff02Yusuf T. Mobile            return radius <= Math.max(mRadius,accuracy);
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "ProximityAlert{"
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Integer.toHexString(System.identityHashCode(this))
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " uid " + mUid + mIntent + "}";
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void dump(PrintWriter pw, String prefix) {
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + this);
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mLatitude=" + mLatitude + " mLongitude=" + mLongitude);
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mRadius=" + mRadius + " mExpiration=" + mExpiration);
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mIntent=" + mIntent);
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mLocation:");
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocation.dump(new PrintWriterPrinter(pw), prefix + "  ");
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Listener for receiving locations to trigger proximity alerts
111448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    class ProximityListener extends ILocationListener.Stub implements PendingIntent.OnFinished {
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean isGpsAvailable = false;
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Note: this is called with the lock held.
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onLocationChanged(Location loc) {
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If Gps is available, then ignore updates from NetworkLocationProvider
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (loc.getProvider().equals(LocationManager.GPS_PROVIDER)) {
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                isGpsAvailable = true;
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isGpsAvailable && loc.getProvider().equals(LocationManager.NETWORK_PROVIDER)) {
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Process proximity alerts
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long now = System.currentTimeMillis();
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            double latitude = loc.getLatitude();
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            double longitude = loc.getLongitude();
11332d2078aa1d6e31063f565a20b717f3b8908fff02Yusuf T. Mobile            float accuracy = loc.getAccuracy();
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<PendingIntent> intentsToRemove = null;
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (ProximityAlert alert : mProximityAlerts.values()) {
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PendingIntent intent = alert.getIntent();
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long expiration = alert.getExpiration();
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((expiration == -1) || (now <= expiration)) {
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    boolean entered = mProximitiesEntered.contains(alert);
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    boolean inProximity =
11432d2078aa1d6e31063f565a20b717f3b8908fff02Yusuf T. Mobile                        alert.isInProximity(latitude, longitude, accuracy);
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!entered && inProximity) {
1145105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        if (LOCAL_LOGV) {
11468a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            Slog.v(TAG, "Entered alert");
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mProximitiesEntered.add(alert);
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Intent enteredIntent = new Intent();
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        enteredIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, true);
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        try {
11520528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                            synchronized (this) {
11530528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                                // synchronize to ensure incrementPendingBroadcasts()
115448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // is called before decrementPendingBroadcasts()
115548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                intent.send(mContext, 0, enteredIntent, this, mLocationHandler);
115648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // call this after broadcasting so we do not increment
115748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // if we throw an exeption.
11580528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                                incrementPendingBroadcasts();
115948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            }
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } catch (PendingIntent.CanceledException e) {
1161105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                            if (LOCAL_LOGV) {
11628a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                                Slog.v(TAG, "Canceled proximity alert: " + alert, e);
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (intentsToRemove == null) {
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                intentsToRemove = new ArrayList<PendingIntent>();
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            intentsToRemove.add(intent);
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else if (entered && !inProximity) {
1170105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        if (LOCAL_LOGV) {
11718a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            Slog.v(TAG, "Exited alert");
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mProximitiesEntered.remove(alert);
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Intent exitedIntent = new Intent();
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        exitedIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, false);
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        try {
11770528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                            synchronized (this) {
11780528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                                // synchronize to ensure incrementPendingBroadcasts()
117948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // is called before decrementPendingBroadcasts()
118048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                intent.send(mContext, 0, exitedIntent, this, mLocationHandler);
118148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // call this after broadcasting so we do not increment
118248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // if we throw an exeption.
11830528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                                incrementPendingBroadcasts();
118448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            }
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } catch (PendingIntent.CanceledException e) {
1186105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                            if (LOCAL_LOGV) {
11878a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                                Slog.v(TAG, "Canceled proximity alert: " + alert, e);
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (intentsToRemove == null) {
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                intentsToRemove = new ArrayList<PendingIntent>();
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            intentsToRemove.add(intent);
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Mark alert for expiration
1197105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    if (LOCAL_LOGV) {
11988a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        Slog.v(TAG, "Expiring proximity alert: " + alert);
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (intentsToRemove == null) {
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        intentsToRemove = new ArrayList<PendingIntent>();
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    intentsToRemove.add(alert.getIntent());
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Remove expired alerts
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (intentsToRemove != null) {
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (PendingIntent i : intentsToRemove) {
12108fff6451476334fbef30a080f46f37d552257e9aSean Foy                    ProximityAlert alert = mProximityAlerts.get(i);
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mProximitiesEntered.remove(alert);
12128fff6451476334fbef30a080f46f37d552257e9aSean Foy                    removeProximityAlertLocked(i);
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Note: this is called with the lock held.
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onProviderDisabled(String provider) {
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (provider.equals(LocationManager.GPS_PROVIDER)) {
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                isGpsAvailable = false;
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Note: this is called with the lock held.
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onProviderEnabled(String provider) {
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ignore
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Note: this is called with the lock held.
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onStatusChanged(String provider, int status, Bundle extras) {
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((provider.equals(LocationManager.GPS_PROVIDER)) &&
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (status != LocationProvider.AVAILABLE)) {
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                isGpsAvailable = false;
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
123648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
123748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        public void onSendFinished(PendingIntent pendingIntent, Intent intent,
123848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                int resultCode, String resultData, Bundle resultExtras) {
12390528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            // synchronize to ensure incrementPendingBroadcasts()
12400528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            // is called before decrementPendingBroadcasts()
12410528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            synchronized (this) {
12420528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                decrementPendingBroadcasts();
12430528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
124448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addProximityAlert(double latitude, double longitude,
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float radius, long expiration, PendingIntent intent) {
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
12502f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                addProximityAlertLocked(latitude, longitude, radius, expiration, intent);
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
12553b9ef08bbbdc95a609fa7883d6fff4b4fd22e33cMike Lockwood        } catch (IllegalArgumentException iae) {
12563b9ef08bbbdc95a609fa7883d6fff4b4fd22e33cMike Lockwood            throw iae;
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
12588a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "addProximityAlert got exception:", e);
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void addProximityAlertLocked(double latitude, double longitude,
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float radius, long expiration, PendingIntent intent) {
1264105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
12658a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.v(TAG, "addProximityAlert: latitude = " + latitude +
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ", longitude = " + longitude +
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ", expiration = " + expiration +
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ", intent = " + intent);
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Require ability to access all providers for now
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isAllowedProviderSafe(LocationManager.GPS_PROVIDER) ||
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            !isAllowedProviderSafe(LocationManager.NETWORK_PROVIDER)) {
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (expiration != -1) {
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            expiration += System.currentTimeMillis();
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ProximityAlert alert = new ProximityAlert(Binder.getCallingUid(),
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                latitude, longitude, radius, expiration, intent);
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProximityAlerts.put(intent, alert);
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
128448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        if (mProximityReceiver == null) {
128548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            mProximityListener = new ProximityListener();
128648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            mProximityReceiver = new Receiver(mProximityListener);
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
128895427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            for (int i = mProviders.size() - 1; i >= 0; i--) {
1289d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                LocationProviderInterface provider = mProviders.get(i);
129048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver);
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeProximityAlert(PendingIntent intent) {
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
12972f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               removeProximityAlertLocked(intent);
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
13023b9ef08bbbdc95a609fa7883d6fff4b4fd22e33cMike Lockwood        } catch (IllegalArgumentException iae) {
13033b9ef08bbbdc95a609fa7883d6fff4b4fd22e33cMike Lockwood            throw iae;
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
13058a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "removeProximityAlert got exception:", e);
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void removeProximityAlertLocked(PendingIntent intent) {
1310105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
13118a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.v(TAG, "removeProximityAlert: intent = " + intent);
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProximityAlerts.remove(intent);
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mProximityAlerts.size() == 0) {
131648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            removeUpdatesLocked(mProximityReceiver);
131748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            mProximityReceiver = null;
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProximityListener = null;
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     }
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1323628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood     * @return null if the provider does not exist
1324f2db9fb0f877057a9ef56908d54f3c95fc3fd552Alexey Tarasov     * @throws SecurityException if the provider is not allowed to be
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * accessed by the caller
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Bundle getProviderInfo(String provider) {
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
13292f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _getProviderInfoLocked(provider);
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
13343b9ef08bbbdc95a609fa7883d6fff4b4fd22e33cMike Lockwood        } catch (IllegalArgumentException iae) {
13353b9ef08bbbdc95a609fa7883d6fff4b4fd22e33cMike Lockwood            throw iae;
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
13378a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "_getProviderInfo got exception:", e);
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Bundle _getProviderInfoLocked(String provider) {
1343d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
1344223e84d7336db189060f3f766a66037af8690496Mike Lockwood        if (p == null) {
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bundle b = new Bundle();
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("network", p.requiresNetwork());
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("satellite", p.requiresSatellite());
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("cell", p.requiresCell());
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("cost", p.hasMonetaryCost());
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("altitude", p.supportsAltitude());
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("speed", p.supportsSpeed());
13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("bearing", p.supportsBearing());
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putInt("power", p.getPowerRequirement());
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putInt("accuracy", p.getAccuracy());
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return b;
13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isProviderEnabled(String provider) {
13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
13662f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _isProviderEnabledLocked(provider);
13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
13713b9ef08bbbdc95a609fa7883d6fff4b4fd22e33cMike Lockwood        } catch (IllegalArgumentException iae) {
13723b9ef08bbbdc95a609fa7883d6fff4b4fd22e33cMike Lockwood            throw iae;
13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
13748a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "isProviderEnabled got exception:", e);
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1379a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood    public void reportLocation(Location location, boolean passive) {
1380275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
1381275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood                != PackageManager.PERMISSION_GRANTED) {
1382275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood            throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
1383275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        }
1384275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood
13854e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location);
13864e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location);
1387a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        m.arg1 = (passive ? 1 : 0);
13884e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        mLocationHandler.sendMessageAtFrontOfQueue(m);
13894e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    }
13904e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean _isProviderEnabledLocked(String provider) {
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1394d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("provider=" + provider);
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return isAllowedBySettingsLocked(provider);
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Location getLastKnownLocation(String provider) {
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
14032f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _getLastKnownLocationLocked(provider);
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
14083b9ef08bbbdc95a609fa7883d6fff4b4fd22e33cMike Lockwood        } catch (IllegalArgumentException iae) {
14093b9ef08bbbdc95a609fa7883d6fff4b4fd22e33cMike Lockwood            throw iae;
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
14118a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "getLastKnownLocation got exception:", e);
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Location _getLastKnownLocationLocked(String provider) {
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1419d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("provider=" + provider);
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isAllowedBySettingsLocked(provider)) {
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14289aa1fa2d3612d1d8ffeae6552d65669f4ca194d9Mike Lockwood        return mLastKnownLocation.get(provider);
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean shouldBroadcastSafe(Location loc, Location lastLoc, UpdateRecord record) {
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Always broadcast the first update
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (lastLoc == null) {
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Don't broadcast same location again regardless of condition
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO - we should probably still rebroadcast if user explicitly sets a minTime > 0
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (loc.getTime() == lastLoc.getTime()) {
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Check whether sufficient distance has been traveled
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        double minDistance = record.mMinDistance;
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (minDistance > 0.0) {
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (loc.distanceTo(lastLoc) <= minDistance) {
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1454a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood    private void handleLocationChangedLocked(Location location, boolean passive) {
1455a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (records == null || records.size() == 0) {
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1461d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14664e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        // Update last known location for provider
14674e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        Location lastLocation = mLastKnownLocation.get(provider);
14684e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        if (lastLocation == null) {
14694e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood            mLastKnownLocation.put(provider, new Location(location));
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14714e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood            lastLocation.set(location);
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Fetch latest status update time
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long newStatusUpdateTime = p.getStatusUpdateTime();
14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14777ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood       // Get latest status
14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bundle extras = new Bundle();
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int status = p.getStatus(extras);
14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<Receiver> deadReceivers = null;
14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Broadcast location or status to all listeners
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = records.size();
14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0; i<N; i++) {
14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            UpdateRecord r = records.get(i);
14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Receiver receiver = r.mReceiver;
14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14892f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            Location lastLoc = r.mLastFixBroadcast;
14904e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood            if ((lastLoc == null) || shouldBroadcastSafe(location, lastLoc, r)) {
14914e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                if (lastLoc == null) {
14924e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    lastLoc = new Location(location);
14932f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    r.mLastFixBroadcast = lastLoc;
14944e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                } else {
14954e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    lastLoc.set(location);
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14974e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                if (!receiver.callLocationChangedLocked(location)) {
14988a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
14994e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    if (deadReceivers == null) {
15004e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                        deadReceivers = new ArrayList<Receiver>();
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15024e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    deadReceivers.add(receiver);
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15062f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            long prevStatusUpdateTime = r.mLastStatusBroadcast;
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((newStatusUpdateTime > prevStatusUpdateTime) &&
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15102f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                r.mLastStatusBroadcast = newStatusUpdateTime;
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!receiver.callStatusChangedLocked(provider, status, extras)) {
15128a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (deadReceivers == null) {
15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        deadReceivers = new ArrayList<Receiver>();
15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!deadReceivers.contains(receiver)) {
15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        deadReceivers.add(receiver);
15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (deadReceivers != null) {
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=deadReceivers.size()-1; i>=0; i--) {
15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeUpdatesLocked(deadReceivers.get(i));
15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class LocationWorkerHandler extends Handler {
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void handleMessage(Message msg) {
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
15354e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                if (msg.what == MESSAGE_LOCATION_CHANGED) {
15364e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    // log("LocationWorkerHandler: MESSAGE_LOCATION_CHANGED!");
15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15382f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    synchronized (mLock) {
15394e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                        Location location = (Location) msg.obj;
1540fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                        String provider = location.getProvider();
1541a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                        boolean passive = (msg.arg1 == 1);
1542a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood
1543a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                        if (!passive) {
1544a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                            // notify other providers of the new location
1545a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                            for (int i = mProviders.size() - 1; i >= 0; i--) {
1546a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                                LocationProviderInterface p = mProviders.get(i);
1547a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                                if (!provider.equals(p.getName())) {
1548a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                                    p.updateLocation(location);
1549a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                                }
155098cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood                            }
155198cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood                        }
155298cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood
1553fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                        if (isAllowedBySettingsLocked(provider)) {
1554a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                            handleLocationChangedLocked(location, passive);
15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (Exception e) {
15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Log, don't crash!
15608a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.e(TAG, "Exception in LocationWorkerHandler.handleMessage:", e);
15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15650528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
15660528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        @Override
15670528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        public void onReceive(Context context, Intent intent) {
15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String action = intent.getAction();
156921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            boolean queryRestart = action.equals(Intent.ACTION_QUERY_PACKAGE_RESTART);
157021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            if (queryRestart
157121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    || action.equals(Intent.ACTION_PACKAGE_REMOVED)
157208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    || action.equals(Intent.ACTION_PACKAGE_RESTARTED)
1573b56ae20b22fd7283df32072a431ab6d4965f3c1bSuchi Amalapurapu                    || action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
15742f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                synchronized (mLock) {
157508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    int uidList[] = null;
1576b56ae20b22fd7283df32072a431ab6d4965f3c1bSuchi Amalapurapu                    if (action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
157708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        uidList = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
157808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    } else {
157908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        uidList = new int[]{intent.getIntExtra(Intent.EXTRA_UID, -1)};
158008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    }
158108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    if (uidList == null || uidList.length == 0) {
158208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        return;
158308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    }
158408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    for (int uid : uidList) {
158508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        if (uid >= 0) {
158608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            ArrayList<Receiver> removedRecs = null;
158708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            for (ArrayList<UpdateRecord> i : mRecordsByProvider.values()) {
158808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                for (int j=i.size()-1; j>=0; j--) {
158908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    UpdateRecord ur = i.get(j);
159008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    if (ur.mReceiver.isPendingIntent() && ur.mUid == uid) {
159121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                        if (queryRestart) {
159221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                            setResultCode(Activity.RESULT_OK);
159321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                            return;
159421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                        }
159508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                        if (removedRecs == null) {
159608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                            removedRecs = new ArrayList<Receiver>();
159708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                        }
159808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                        if (!removedRecs.contains(ur.mReceiver)) {
159908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                            removedRecs.add(ur.mReceiver);
160008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                        }
16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    }
16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
160408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            ArrayList<ProximityAlert> removedAlerts = null;
160508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            for (ProximityAlert i : mProximityAlerts.values()) {
160608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                if (i.mUid == uid) {
160721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    if (queryRestart) {
160821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                        setResultCode(Activity.RESULT_OK);
160921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                        return;
161021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    }
161108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    if (removedAlerts == null) {
161208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                        removedAlerts = new ArrayList<ProximityAlert>();
161308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    }
161408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    if (!removedAlerts.contains(i)) {
161508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                        removedAlerts.add(i);
161608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    }
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
161908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            if (removedRecs != null) {
162008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                for (int i=removedRecs.size()-1; i>=0; i--) {
162108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    removeUpdatesLocked(removedRecs.get(i));
162208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                }
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
162408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            if (removedAlerts != null) {
162508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                for (int i=removedAlerts.size()-1; i>=0; i--) {
162608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    removeProximityAlertLocked(removedAlerts.get(i).mIntent);
162708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                }
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16320528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
16339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean noConnectivity =
16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!noConnectivity) {
16364df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    mNetworkState = LocationProvider.AVAILABLE;
16374df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                } else {
16384df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
164003d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                NetworkInfo info =
164108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    (NetworkInfo)intent.getExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Notify location providers of current network state
16442f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                synchronized (mLock) {
164515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    for (int i = mProviders.size() - 1; i >= 0; i--) {
1646d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                        LocationProviderInterface provider = mProviders.get(i);
1647f19a785e15d9ffa1c1e56c254af082fc87aa1f3cMike Lockwood                        if (provider.requiresNetwork()) {
164803d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                            provider.updateNetworkState(mNetworkState, info);
16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16540528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    };
16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Wake locks
16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16580528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private void incrementPendingBroadcasts() {
16590528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        synchronized (mWakeLock) {
16600528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (mPendingBroadcasts++ == 0) {
16610528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                try {
16620528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    mWakeLock.acquire();
16630528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    log("Acquired wakelock");
16640528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                } catch (Exception e) {
16650528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // This is to catch a runtime exception thrown when we try to release an
16660528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // already released lock.
16678a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.e(TAG, "exception in acquireWakeLock()", e);
16680528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                }
16690528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
167048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
167148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
167248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
167348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private void decrementPendingBroadcasts() {
16740528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        synchronized (mWakeLock) {
167548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (--mPendingBroadcasts == 0) {
16760528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                try {
16770528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // Release wake lock
16780528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    if (mWakeLock.isHeld()) {
16790528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                        mWakeLock.release();
16800528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                        log("Released wakelock");
16810528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    } else {
16820528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                        log("Can't release wakelock again!");
16830528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    }
16840528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                } catch (Exception e) {
16850528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // This is to catch a runtime exception thrown when we try to release an
16860528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // already released lock.
16878a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.e(TAG, "exception in releaseWakeLock()", e);
16880528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                }
168948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
169048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
169148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
169248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Geocoder
16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String getFromLocation(double latitude, double longitude, int maxResults,
169634901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwood            GeocoderParams params, List<Address> addrs) {
1697a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        if (mGeocodeProvider != null) {
1698628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood            return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
1699628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                    params, addrs);
17009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1701a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        return null;
17029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1704a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood
17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String getFromLocationName(String locationName,
1706a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            double lowerLeftLatitude, double lowerLeftLongitude,
1707a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            double upperRightLatitude, double upperRightLongitude, int maxResults,
170834901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwood            GeocoderParams params, List<Address> addrs) {
1709a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood
1710a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        if (mGeocodeProvider != null) {
1711628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood            return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
1712628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                    lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
1713628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                    maxResults, params, addrs);
17149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1715a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        return null;
17169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Mock Providers
17199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void checkMockPermissionsSafe() {
17219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(),
17229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1;
17239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!allowMocks) {
17249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting");
17259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) !=
17289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PackageManager.PERMISSION_GRANTED) {
17299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission");
17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite,
17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
17359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
17369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1738a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
1739a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood            throw new IllegalArgumentException("Cannot mock the passive location provider");
1740a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        }
1741a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood
174286328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood        long identity = Binder.clearCallingIdentity();
17432f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
17444e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood            MockProvider provider = new MockProvider(name, this,
17454e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                requiresNetwork, requiresSatellite,
17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                requiresCell, hasMonetaryCost, supportsAltitude,
17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                supportsSpeed, supportsBearing, powerRequirement, accuracy);
17487566c1debebe072af76411e11d96810fd1409482Mike Lockwood            // remove the real provider if we are replacing GPS or network provider
17497566c1debebe072af76411e11d96810fd1409482Mike Lockwood            if (LocationManager.GPS_PROVIDER.equals(name)
17507566c1debebe072af76411e11d96810fd1409482Mike Lockwood                    || LocationManager.NETWORK_PROVIDER.equals(name)) {
1751d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                LocationProviderInterface p = mProvidersByName.get(name);
1752d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                if (p != null) {
1753d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                    p.enableLocationTracking(false);
1754d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                    removeProvider(p);
17557566c1debebe072af76411e11d96810fd1409482Mike Lockwood                }
17567566c1debebe072af76411e11d96810fd1409482Mike Lockwood            }
175715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (mProvidersByName.get(name) != null) {
17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1760d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            addProvider(provider);
17617ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mMockProviders.put(name, provider);
17627566c1debebe072af76411e11d96810fd1409482Mike Lockwood            mLastKnownLocation.put(name, null);
17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
176586328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood        Binder.restoreCallingIdentity(identity);
17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeTestProvider(String provider) {
17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17702f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
17717ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
17727ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
177586328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            long identity = Binder.clearCallingIdentity();
177615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            removeProvider(mProvidersByName.get(provider));
17777ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mMockProviders.remove(mockProvider);
17787566c1debebe072af76411e11d96810fd1409482Mike Lockwood            // reinstall real provider if we were mocking GPS or network provider
17797566c1debebe072af76411e11d96810fd1409482Mike Lockwood            if (LocationManager.GPS_PROVIDER.equals(provider) &&
17807566c1debebe072af76411e11d96810fd1409482Mike Lockwood                    mGpsLocationProvider != null) {
17817566c1debebe072af76411e11d96810fd1409482Mike Lockwood                addProvider(mGpsLocationProvider);
17827566c1debebe072af76411e11d96810fd1409482Mike Lockwood            } else if (LocationManager.NETWORK_PROVIDER.equals(provider) &&
17837566c1debebe072af76411e11d96810fd1409482Mike Lockwood                    mNetworkLocationProvider != null) {
17847566c1debebe072af76411e11d96810fd1409482Mike Lockwood                addProvider(mNetworkLocationProvider);
17857566c1debebe072af76411e11d96810fd1409482Mike Lockwood            }
17867566c1debebe072af76411e11d96810fd1409482Mike Lockwood            mLastKnownLocation.put(provider, null);
17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
178886328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            Binder.restoreCallingIdentity(identity);
17899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderLocation(String provider, Location loc) {
17939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17942f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
17957ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
17967ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
17989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
179995427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
180095427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            long identity = Binder.clearCallingIdentity();
18017ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.setLocation(loc);
180295427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            Binder.restoreCallingIdentity(identity);
18039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderLocation(String provider) {
18079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18082f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18097ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18107ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18137ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.clearLocation();
18149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderEnabled(String provider, boolean enabled) {
18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18192f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18207ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18217ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
182486328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            long identity = Binder.clearCallingIdentity();
18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (enabled) {
18267ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                mockProvider.enable();
18279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEnabledProviders.add(provider);
18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDisabledProviders.remove(provider);
18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
18307ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                mockProvider.disable();
18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEnabledProviders.remove(provider);
18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDisabledProviders.add(provider);
18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
183586328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            Binder.restoreCallingIdentity(identity);
18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderEnabled(String provider) {
18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18412f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18427ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18437ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
184686328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            long identity = Binder.clearCallingIdentity();
18479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEnabledProviders.remove(provider);
18489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDisabledProviders.remove(provider);
18499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
185086328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            Binder.restoreCallingIdentity(identity);
18519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
18559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18562f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18577ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18587ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18617ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.setStatus(status, extras, updateTime);
18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderStatus(String provider) {
18669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18672f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18687ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18697ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18727ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.clearStatus();
18739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void log(String log) {
18779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Log.isLoggable(TAG, Log.VERBOSE)) {
18788a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.d(TAG, log);
18799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
18839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
18850528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            pw.println("Permission Denial: can't dump LocationManagerService from from pid="
18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Binder.getCallingPid()
18879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", uid=" + Binder.getCallingUid());
18889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
18899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18912f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("Current Location Manager state:");
18939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  sProvidersLoaded=" + sProvidersLoaded);
18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Listeners:");
18952f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            int N = mReceivers.size();
18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
18972f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                pw.println("    " + mReceivers.get(i));
18989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Location Listeners:");
19002f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            for (Receiver i : mReceivers.values()) {
19012f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                pw.println("    " + i + ":");
19022f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                for (Map.Entry<String,UpdateRecord> j : i.mUpdateRecords.entrySet()) {
19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("      " + j.getKey() + ":");
19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    j.getValue().dump(pw, "        ");
19059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Records by Provider:");
19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (Map.Entry<String, ArrayList<UpdateRecord>> i
19099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    : mRecordsByProvider.entrySet()) {
19109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("    " + i.getKey() + ":");
19119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (UpdateRecord j : i.getValue()) {
19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("      " + j + ":");
19139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    j.dump(pw, "        ");
19149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Last Known Locations:");
19179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (Map.Entry<String, Location> i
19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    : mLastKnownLocation.entrySet()) {
19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("    " + i.getKey() + ":");
19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                i.getValue().dump(new PrintWriterPrinter(pw), "      ");
19219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mProximityAlerts.size() > 0) {
19239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Proximity Alerts:");
19249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (Map.Entry<PendingIntent, ProximityAlert> i
19259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        : mProximityAlerts.entrySet()) {
19269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i.getKey() + ":");
19279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    i.getValue().dump(pw, "      ");
19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mProximitiesEntered.size() > 0) {
19319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Proximities Entered:");
19329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (ProximityAlert i : mProximitiesEntered) {
19339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i + ":");
19349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    i.dump(pw, "      ");
19359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
193748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            pw.println("  mProximityReceiver=" + mProximityReceiver);
19389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  mProximityListener=" + mProximityListener);
19399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mEnabledProviders.size() > 0) {
19409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Enabled Providers:");
19419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (String i : mEnabledProviders) {
19429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i);
19439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mDisabledProviders.size() > 0) {
19479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Disabled Providers:");
19489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (String i : mDisabledProviders) {
19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i);
19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mMockProviders.size() > 0) {
19549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Mock Providers:");
19559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
19567ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                    i.getValue().dump(pw, "      ");
19579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19593c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger            for (LocationProviderInterface provider: mProviders) {
19603c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger                String state = provider.getInternalState();
19613c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger                if (state != null) {
19623c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger                    pw.println(provider.getName() + " Internal State:");
19633c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger                    pw.write(state);
19643c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger                }
19653c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger            }
19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1969