LocationManagerService.java revision a4903f254b4711c8fc0ac5f7e3d605f4dce34f35
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashSet;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map;
269637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwoodimport java.util.Observable;
279637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwoodimport java.util.Observer;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.PendingIntent;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver;
32628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwoodimport android.content.ComponentName;
339637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwoodimport android.content.ContentQueryMap;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter;
38628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwoodimport android.content.ServiceConnection;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
40628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwoodimport android.content.res.Resources;
419637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwoodimport android.database.Cursor;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Address;
4334901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwoodimport android.location.GeocoderParams;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.IGpsStatusListener;
4515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwoodimport android.location.IGpsStatusProvider;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.ILocationListener;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.ILocationManager;
4822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport android.location.INetInitiatedListener;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Location;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationManager;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationProvider;
52d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwoodimport android.location.LocationProviderInterface;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.ConnectivityManager;
5403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwoodimport android.net.NetworkInfo;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
603d12b51ee38537f6760a833618948f936e75561dMike Lockwoodimport android.os.Looper;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager;
63e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwoodimport android.os.Process;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.PrintWriterPrinter;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
69628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwoodimport com.android.internal.location.GeocoderProxy;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.location.GpsLocationProvider;
71628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwoodimport com.android.internal.location.GpsNetInitiatedHandler;
72e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwoodimport com.android.internal.location.LocationProviderProxy;
737ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwoodimport com.android.internal.location.MockProvider;
74a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwoodimport com.android.internal.location.PassiveProvider;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The service class that manages LocationProviders and issues location
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * updates and alerts.
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
823d12b51ee38537f6760a833618948f936e75561dMike Lockwoodpublic class LocationManagerService extends ILocationManager.Stub implements Runnable {
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "LocationManagerService";
84105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final boolean LOCAL_LOGV = false;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // The last time a location was written, by provider name.
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<String,Long> mLastWriteTime = new HashMap<String,Long>();
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_FINE_LOCATION =
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        android.Manifest.permission.ACCESS_FINE_LOCATION;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_COARSE_LOCATION =
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        android.Manifest.permission.ACCESS_COARSE_LOCATION;
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_MOCK_LOCATION =
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        android.Manifest.permission.ACCESS_MOCK_LOCATION;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
97275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood    private static final String INSTALL_LOCATION_PROVIDER =
98275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Set of providers that are explicitly enabled
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Set<String> mEnabledProviders = new HashSet<String>();
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Set of providers that are explicitly disabled
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Set<String> mDisabledProviders = new HashSet<String>();
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Locations, status values, and extras for mock providers
1077ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood    private final HashMap<String,MockProvider> mMockProviders = new HashMap<String,MockProvider>();
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean sProvidersLoaded = false;
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Context mContext;
112628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood    private GeocoderProxy mGeocodeProvider;
11315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private IGpsStatusProvider mGpsStatusProvider;
11422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private INetInitiatedListener mNetInitiatedListener;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private LocationWorkerHandler mLocationHandler;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1177566c1debebe072af76411e11d96810fd1409482Mike Lockwood    // Cache the real providers for use in addTestProvider() and removeTestProvider()
118d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood     LocationProviderInterface mNetworkLocationProvider;
119d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood     LocationProviderInterface mGpsLocationProvider;
1207566c1debebe072af76411e11d96810fd1409482Mike Lockwood
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Handler messages
1224e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    private static final int MESSAGE_LOCATION_CHANGED = 1;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1240528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    // wakelock variables
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final static String WAKELOCK_KEY = "LocationManagerService";
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private PowerManager.WakeLock mWakeLock = null;
12748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private int mPendingBroadcasts;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1302f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood     * List of all receivers.
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1322f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final HashMap<Object, Receiver> mReceivers = new HashMap<Object, Receiver>();
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
13515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    /**
13615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood     * List of location providers.
13715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood     */
138d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    private final ArrayList<LocationProviderInterface> mProviders =
139d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        new ArrayList<LocationProviderInterface>();
140d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    private final HashMap<String, LocationProviderInterface> mProvidersByName
141d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        = new HashMap<String, LocationProviderInterface>();
14215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1442f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood     * Object used internally for synchronization
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1462f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final Object mLock = new Object();
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Mapping from provider name to all its UpdateRecords
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashMap<String,ArrayList<UpdateRecord>> mRecordsByProvider =
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashMap<String,ArrayList<UpdateRecord>>();
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Proximity listeners
15548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private Receiver mProximityReceiver = null;
15648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private ILocationListener mProximityListener = null;
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<PendingIntent,ProximityAlert> mProximityAlerts =
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashMap<PendingIntent,ProximityAlert>();
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashSet<ProximityAlert> mProximitiesEntered =
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashSet<ProximityAlert>();
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Last known location for each provider
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<String,Location> mLastKnownLocation =
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashMap<String,Location>();
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1664df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    private int mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
1674df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
1689637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood    // for Settings change notification
1699637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood    private ContentQueryMap mSettings;
1709637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A wrapper class holding either an ILocationListener or a PendingIntent to receive
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * location updates.
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ILocationListener mListener;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final PendingIntent mPendingIntent;
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Object mKey;
1792f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
18048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        int mPendingBroadcasts;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1822f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver(ILocationListener listener) {
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = listener;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPendingIntent = null;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mKey = listener.asBinder();
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1882f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver(PendingIntent intent) {
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPendingIntent = intent;
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = null;
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mKey = intent;
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean equals(Object otherObj) {
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (otherObj instanceof Receiver) {
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mKey.equals(
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((Receiver)otherObj).mKey);
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int hashCode() {
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mKey.hashCode();
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2073681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return "Receiver{"
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + Integer.toHexString(System.identityHashCode(this))
2132f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                        + " Listener " + mKey + "}";
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return "Receiver{"
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + Integer.toHexString(System.identityHashCode(this))
2172f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                        + " Intent " + mKey + "}";
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean isListener() {
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mListener != null;
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean isPendingIntent() {
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mPendingIntent != null;
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ILocationListener getListener() {
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mListener;
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("Request for non-existent listener");
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public PendingIntent getPendingIntent() {
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mPendingIntent != null) {
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mPendingIntent;
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("Request for non-existent intent");
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
24648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
24748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
24848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
24948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mListener.onStatusChanged(provider, status, extras);
25048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (mListener != mProximityListener) {
25148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // call this after broadcasting so we do not increment
25248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // if we throw an exeption.
25348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            incrementPendingBroadcastsLocked();
25448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
25548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent statusChanged = new Intent();
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                statusChanged.putExtras(extras);
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
26448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
26548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
26648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
26748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler);
26848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
26948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
27048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
27148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (PendingIntent.CanceledException e) {
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean callLocationChangedLocked(Location location) {
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
28248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
28348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
28448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
28548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mListener.onLocationChanged(location);
28648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (mListener != mProximityListener) {
28748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // call this after broadcasting so we do not increment
28848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // if we throw an exeption.
28948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            incrementPendingBroadcastsLocked();
29048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
29148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent locationChanged = new Intent();
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, location);
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
29948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
30048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
30148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
30248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler);
30348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
30448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
30548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
30648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
30748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                } catch (PendingIntent.CanceledException e) {
30848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    return false;
30948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
31048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
31148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            return true;
31248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
31348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
31448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        public boolean callProviderEnabledLocked(String provider, boolean enabled) {
31548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (mListener != null) {
31648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                try {
31748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
31848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
31948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
32048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (enabled) {
32148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            mListener.onProviderEnabled(provider);
32248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        } else {
32348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            mListener.onProviderDisabled(provider);
32448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
32548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (mListener != mProximityListener) {
32648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // call this after broadcasting so we do not increment
32748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // if we throw an exeption.
32848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            incrementPendingBroadcastsLocked();
32948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
33048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
33148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                } catch (RemoteException e) {
33248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    return false;
33348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
33448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            } else {
33548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                Intent providerIntent = new Intent();
33648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
33748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                try {
33848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
33948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
34048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
34148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler);
34248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
34348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
34448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
34548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (PendingIntent.CanceledException e) {
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
354105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            if (LOCAL_LOGV) {
355105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                Log.v(TAG, "Location listener died");
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3572f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeUpdatesLocked(this);
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
36048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            synchronized (this) {
36148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                if (mPendingBroadcasts > 0) {
36248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    LocationManagerService.this.decrementPendingBroadcasts();
36348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    mPendingBroadcasts = 0;
36448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
36548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
36648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
36748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
36848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        public void onSendFinished(PendingIntent pendingIntent, Intent intent,
36948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                int resultCode, String resultData, Bundle resultExtras) {
3700528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            synchronized (this) {
3710528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                decrementPendingBroadcastsLocked();
3720528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
37348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
37448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
3750528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // this must be called while synchronized by caller in a synchronized block
37648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        // containing the sending of the broadcaset
37748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        private void incrementPendingBroadcastsLocked() {
37848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (mPendingBroadcasts++ == 0) {
3790528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                LocationManagerService.this.incrementPendingBroadcasts();
38048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
38148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
38248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
3830528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        private void decrementPendingBroadcastsLocked() {
3840528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (--mPendingBroadcasts == 0) {
3850528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                LocationManagerService.this.decrementPendingBroadcasts();
38648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
38748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
38848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
38948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
39048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    public void locationCallbackFinished(ILocationListener listener) {
391080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //Do not use getReceiver here as that will add the ILocationListener to
392080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //the receiver list if it is not found.  If it is not found then the
393080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //LocationListener was removed when it had a pending broadcast and should
394080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //not be added back.
395080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        IBinder binder = listener.asBinder();
396080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        Receiver receiver = mReceivers.get(binder);
39748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        if (receiver != null) {
3980528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            synchronized (receiver) {
3990528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                // so wakelock calls will succeed
4000528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                long identity = Binder.clearCallingIdentity();
4010528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                receiver.decrementPendingBroadcastsLocked();
4020528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                Binder.restoreCallingIdentity(identity);
4030528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood           }
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4079637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood    private final class SettingsObserver implements Observer {
4089637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        public void update(Observable o, Object arg) {
4092f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
4109637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood                updateProvidersLocked();
4119637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood            }
4129637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        }
4139637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood    }
4149637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood
415d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    private void addProvider(LocationProviderInterface provider) {
41615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProviders.add(provider);
41715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProvidersByName.put(provider.getName(), provider);
41815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
41915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
420d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    private void removeProvider(LocationProviderInterface provider) {
42115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProviders.remove(provider);
42215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProvidersByName.remove(provider.getName());
42315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
42415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void loadProviders() {
4262f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sProvidersLoaded) {
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Load providers
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            loadProvidersLocked();
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sProvidersLoaded = true;
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void loadProvidersLocked() {
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            _loadProvidersLocked();
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "Exception loading providers:", e);
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void _loadProvidersLocked() {
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Attempt to load "real" providers first
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (GpsLocationProvider.isSupported()) {
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Create a gps location provider
449d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);
450d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
451d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
452d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            addProvider(gpsProvider);
453d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            mGpsLocationProvider = gpsProvider;
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
456a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        // create a passive location provider, which is always enabled
457a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        PassiveProvider passiveProvider = new PassiveProvider(this);
458a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        addProvider(passiveProvider);
459a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        mEnabledProviders.add(passiveProvider.getName());
460a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood
461628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood        // initialize external network location and geocoder services
462628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood        Resources resources = mContext.getResources();
463628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood        String serviceName = resources.getString(
464628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                com.android.internal.R.string.config_networkLocationProvider);
465628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood        if (serviceName != null) {
466628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood            mNetworkLocationProvider =
467628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                new LocationProviderProxy(mContext, LocationManager.NETWORK_PROVIDER,
468628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                        serviceName, mLocationHandler);
469628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood            addProvider(mNetworkLocationProvider);
470628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood        }
471628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood
472628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood        serviceName = resources.getString(com.android.internal.R.string.config_geocodeProvider);
473628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood        if (serviceName != null) {
474628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood            mGeocodeProvider = new GeocoderProxy(mContext, serviceName);
475628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood        }
476628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateProvidersLocked();
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context the context that the LocationManagerService runs in
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public LocationManagerService(Context context) {
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super();
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
4863d12b51ee38537f6760a833618948f936e75561dMike Lockwood
4873d12b51ee38537f6760a833618948f936e75561dMike Lockwood        Thread thread = new Thread(null, this, "LocationManagerService");
4883d12b51ee38537f6760a833618948f936e75561dMike Lockwood        thread.start();
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
490105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
491105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "Constructed LocationManager Service");
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4933d12b51ee38537f6760a833618948f936e75561dMike Lockwood    }
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4953d12b51ee38537f6760a833618948f936e75561dMike Lockwood    private void initialize() {
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Create a wake lock, needs to be done before calling loadProviders() below
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
4990528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Load providers
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        loadProviders();
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Register for Network (Wifi or Mobile) updates
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IntentFilter intentFilter = new IntentFilter();
5050528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
5060528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // Register for Package Manager updates
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
5090528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        mContext.registerReceiver(mBroadcastReceiver, intentFilter);
510b56ae20b22fd7283df32072a431ab6d4965f3c1bSuchi Amalapurapu        IntentFilter sdFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
51108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu        mContext.registerReceiver(mBroadcastReceiver, sdFilter);
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5139637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        // listen for settings changes
5149637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        ContentResolver resolver = mContext.getContentResolver();
5159637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        Cursor settingsCursor = resolver.query(Settings.Secure.CONTENT_URI, null,
5169637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood                "(" + Settings.System.NAME + "=?)",
5179637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood                new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
5189637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood                null);
5199637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mLocationHandler);
5209637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        SettingsObserver settingsObserver = new SettingsObserver();
5219637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        mSettings.addObserver(settingsObserver);
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5243d12b51ee38537f6760a833618948f936e75561dMike Lockwood    public void run()
5253d12b51ee38537f6760a833618948f936e75561dMike Lockwood    {
5263d12b51ee38537f6760a833618948f936e75561dMike Lockwood        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
5273d12b51ee38537f6760a833618948f936e75561dMike Lockwood        Looper.prepare();
5283d12b51ee38537f6760a833618948f936e75561dMike Lockwood        mLocationHandler = new LocationWorkerHandler();
5293d12b51ee38537f6760a833618948f936e75561dMike Lockwood        initialize();
5303d12b51ee38537f6760a833618948f936e75561dMike Lockwood        Looper.loop();
5313d12b51ee38537f6760a833618948f936e75561dMike Lockwood    }
5323d12b51ee38537f6760a833618948f936e75561dMike Lockwood
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean isAllowedBySettingsLocked(String provider) {
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabledProviders.contains(provider)) {
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDisabledProviders.contains(provider)) {
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Use system settings
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ContentResolver resolver = mContext.getContentResolver();
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5438eb3ea659761edc2cd5db3acf448059f19389e5eBrad Larson        return Settings.Secure.isLocationProviderEnabled(resolver, provider);
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void checkPermissionsSafe(String provider) {
547a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        if ((LocationManager.GPS_PROVIDER.equals(provider)
548a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                 || LocationManager.PASSIVE_PROVIDER.equals(provider))
549b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (LocationManager.NETWORK_PROVIDER.equals(provider)
554b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)
556b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION)
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException(
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "Requires ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission");
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean isAllowedProviderSafe(String provider) {
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (LocationManager.GPS_PROVIDER.equals(provider)
565b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (LocationManager.NETWORK_PROVIDER.equals(provider)
570b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)
572b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_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
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<String> getAllProviders() {
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
5822f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _getAllProvidersLocked();
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "getAllProviders got exception:", e);
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private List<String> _getAllProvidersLocked() {
594105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
595105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "getAllProviders");
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
59715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        ArrayList<String> out = new ArrayList<String>(mProviders.size());
59815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        for (int i = mProviders.size() - 1; i >= 0; i--) {
599d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            LocationProviderInterface p = mProviders.get(i);
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            out.add(p.getName());
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return out;
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<String> getProviders(boolean enabledOnly) {
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
6072f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _getProvidersLocked(enabledOnly);
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
613105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.e(TAG, "getProviders got exception:", e);
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private List<String> _getProvidersLocked(boolean enabledOnly) {
619105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
620105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "getProviders");
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
62215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        ArrayList<String> out = new ArrayList<String>(mProviders.size());
62315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        for (int i = mProviders.size() - 1; i >= 0; i--) {
624d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            LocationProviderInterface p = mProviders.get(i);
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = p.getName();
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isAllowedProviderSafe(name)) {
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (enabledOnly && !isAllowedBySettingsLocked(name)) {
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                out.add(name);
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return out;
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateProvidersLocked() {
63715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        for (int i = mProviders.size() - 1; i >= 0; i--) {
638d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            LocationProviderInterface p = mProviders.get(i);
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean isEnabled = p.isEnabled();
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = p.getName();
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isEnabled && !shouldBeEnabled) {
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                updateProviderListenersLocked(name, false);
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (!isEnabled && shouldBeEnabled) {
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                updateProviderListenersLocked(name, true);
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateProviderListenersLocked(String provider, boolean enabled) {
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int listeners = 0;
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
655d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<Receiver> deadReceivers = null;
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (records != null) {
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int N = records.size();
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                UpdateRecord record = records.get(i);
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Sends a notification message to the receiver
66848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
66948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    if (deadReceivers == null) {
67048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        deadReceivers = new ArrayList<Receiver>();
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6724686657cee6411eb00235d49b4a8663a96361a00Simon Schoar                    deadReceivers.add(record.mReceiver);
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listeners++;
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (deadReceivers != null) {
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=deadReceivers.size()-1; i>=0; i--) {
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeUpdatesLocked(deadReceivers.get(i));
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (enabled) {
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.enable();
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (listeners > 0) {
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.setMinTime(getMinTimeLocked(provider));
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.enableLocationTracking(true);
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.enableLocationTracking(false);
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.disable();
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long getMinTimeLocked(String provider) {
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long minTime = Long.MAX_VALUE;
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (records != null) {
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=records.size()-1; i>=0; i--) {
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                minTime = Math.min(minTime, records.get(i).mMinTime);
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return minTime;
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class UpdateRecord {
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String mProvider;
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Receiver mReceiver;
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final long mMinTime;
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float mMinDistance;
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int mUid;
7132f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Location mLastFixBroadcast;
7142f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        long mLastStatusBroadcast;
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Note: must be constructed with lock held.
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        UpdateRecord(String provider, long minTime, float minDistance,
7202f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            Receiver receiver, int uid) {
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProvider = provider;
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mReceiver = receiver;
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMinTime = minTime;
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMinDistance = minDistance;
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mUid = uid;
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (records == null) {
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                records = new ArrayList<UpdateRecord>();
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRecordsByProvider.put(provider, records);
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!records.contains(this)) {
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                records.add(this);
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Method to be called when a record will no longer be used.  Calling this multiple times
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * must have the same effect as calling it once.
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void disposeLocked() {
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<UpdateRecord> records = mRecordsByProvider.get(this.mProvider);
7433a76fd627945c1df59aa0318867401e0e53da022Mike Lockwood            if (records != null) {
7443a76fd627945c1df59aa0318867401e0e53da022Mike Lockwood                records.remove(this);
7453a76fd627945c1df59aa0318867401e0e53da022Mike Lockwood            }
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "UpdateRecord{"
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Integer.toHexString(System.identityHashCode(this))
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " " + mProvider + " " + mReceiver + "}";
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void dump(PrintWriter pw, String prefix) {
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + this);
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mProvider=" + mProvider + " mReceiver=" + mReceiver);
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mMinTime=" + mMinTime + " mMinDistance=" + mMinDistance);
7592f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            pw.println(prefix + "mUid=" + mUid);
7602f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            pw.println(prefix + "mLastFixBroadcast:");
7612f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            mLastFixBroadcast.dump(new PrintWriterPrinter(pw), prefix + "  ");
7622f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            pw.println(prefix + "mLastStatusBroadcast=" + mLastStatusBroadcast);
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7662f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private Receiver getReceiver(ILocationListener listener) {
7672f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        IBinder binder = listener.asBinder();
7682f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver receiver = mReceivers.get(binder);
7692f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (receiver == null) {
7702f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            receiver = new Receiver(listener);
7712f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            mReceivers.put(binder, receiver);
7722f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
7732f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            try {
7742f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                if (receiver.isListener()) {
7752f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    receiver.getListener().asBinder().linkToDeath(receiver, 0);
7762f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                }
7772f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            } catch (RemoteException e) {
7782f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                Log.e(TAG, "linkToDeath failed:", e);
7792f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                return null;
7802f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
7812f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
7822f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        return receiver;
7832f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
7842f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
7852f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private Receiver getReceiver(PendingIntent intent) {
7862f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver receiver = mReceivers.get(intent);
7872f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (receiver == null) {
7882f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            receiver = new Receiver(intent);
7892f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            mReceivers.put(intent, receiver);
7902f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
7912f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        return receiver;
7922f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
7932f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
7942f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private boolean providerHasListener(String provider, int uid, Receiver excludedReceiver) {
7952f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
7962f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (records != null) {
7972f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            for (int i = records.size() - 1; i >= 0; i--) {
7982f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                UpdateRecord record = records.get(i);
7992f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                if (record.mUid == uid && record.mReceiver != excludedReceiver) {
8002f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    return true;
8012f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                }
8022f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood           }
8032f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
80495427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood        for (ProximityAlert alert : mProximityAlerts.values()) {
80595427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            if (alert.mUid == uid) {
80695427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood                return true;
8072f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
8082f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
8092f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        return false;
8102f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
8112f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void requestLocationUpdates(String provider,
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long minTime, float minDistance, ILocationListener listener) {
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8162f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
8172f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                requestLocationUpdatesLocked(provider, minTime, minDistance, getReceiver(listener));
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "requestUpdates got exception:", e);
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void requestLocationUpdatesPI(String provider,
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long minTime, float minDistance, PendingIntent intent) {
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8292f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
8302f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                requestLocationUpdatesLocked(provider, minTime, minDistance, getReceiver(intent));
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "requestUpdates got exception:", e);
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void requestLocationUpdatesLocked(String provider,
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long minTime, float minDistance, Receiver receiver) {
841105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
842105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "_requestLocationUpdates: listener = " + receiver);
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
845d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
846d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        if (p == null) {
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("provider=" + provider);
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // so wakelock calls will succeed
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int callingUid = Binder.getCallingUid();
8542f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        boolean newUid = !providerHasListener(provider, callingUid, null);
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identity = Binder.clearCallingIdentity();
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8572f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            UpdateRecord r = new UpdateRecord(provider, minTime, minDistance, receiver, callingUid);
8582f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            UpdateRecord oldRecord = receiver.mUpdateRecords.put(provider, r);
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (oldRecord != null) {
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                oldRecord.disposeLocked();
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8632f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            if (newUid) {
864d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                p.addListener(callingUid);
8652f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
8662f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean isProviderEnabled = isAllowedBySettingsLocked(provider);
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isProviderEnabled) {
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long minTimeForProvider = getMinTimeLocked(provider);
870d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                p.setMinTime(minTimeForProvider);
871d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                p.enableLocationTracking(true);
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
87348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                // Notify the listener that updates are currently disabled
87448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                receiver.callProviderEnabledLocked(provider, false);
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(identity);
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeUpdates(ILocationListener listener) {
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8832f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
8842f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                removeUpdatesLocked(getReceiver(listener));
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "removeUpdates got exception:", e);
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeUpdatesPI(PendingIntent intent) {
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8952f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
8962f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                removeUpdatesLocked(getReceiver(intent));
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "removeUpdates got exception:", e);
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void removeUpdatesLocked(Receiver receiver) {
906105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
907105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "_removeUpdates: listener = " + receiver);
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // so wakelock calls will succeed
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int callingUid = Binder.getCallingUid();
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identity = Binder.clearCallingIdentity();
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
9142f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
9152f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
916080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                synchronized(receiver) {
917080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                    if(receiver.mPendingBroadcasts > 0) {
918080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                        decrementPendingBroadcasts();
919080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                        receiver.mPendingBroadcasts = 0;
920080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                    }
921080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                }
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Record which providers were associated with this listener
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            HashSet<String> providers = new HashSet<String>();
9262f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            HashMap<String,UpdateRecord> oldRecords = receiver.mUpdateRecords;
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (oldRecords != null) {
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Call dispose() on the obsolete update records.
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (UpdateRecord record : oldRecords.values()) {
9302f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    if (!providerHasListener(record.mProvider, callingUid, receiver)) {
931d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                        LocationProviderInterface p = mProvidersByName.get(record.mProvider);
932d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                        if (p != null) {
933d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                            p.removeListener(callingUid);
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    record.disposeLocked();
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Accumulate providers
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                providers.addAll(oldRecords.keySet());
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // See if the providers associated with this listener have any
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // other listeners; if one does, inform it of the new smallest minTime
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // value; if one does not, disable location tracking for it
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (String provider : providers) {
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // If provider is already disabled, don't need to do anything
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!isAllowedBySettingsLocked(provider)) {
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean hasOtherListener = false;
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ArrayList<UpdateRecord> recordsForProvider = mRecordsByProvider.get(provider);
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (recordsForProvider != null && recordsForProvider.size() > 0) {
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    hasOtherListener = true;
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
957d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                LocationProviderInterface p = mProvidersByName.get(provider);
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (p != null) {
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (hasOtherListener) {
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        p.setMinTime(getMinTimeLocked(provider));
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        p.enableLocationTracking(false);
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(identity);
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean addGpsStatusListener(IGpsStatusListener listener) {
97215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mGpsStatusProvider == null) {
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
975b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood        if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) !=
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PackageManager.PERMISSION_GRANTED) {
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
98115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            mGpsStatusProvider.addGpsStatusListener(listener);
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
98315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            Log.e(TAG, "mGpsStatusProvider.addGpsStatusListener failed", e);
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeGpsStatusListener(IGpsStatusListener listener) {
9902f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
99115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            try {
99215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                mGpsStatusProvider.removeGpsStatusListener(listener);
99315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            } catch (Exception e) {
99415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Log.e(TAG, "mGpsStatusProvider.removeGpsStatusListener failed", e);
99515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendExtraCommand(String provider, String command, Bundle extras) {
1000c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood        if (provider == null) {
1001c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood            // throw NullPointerException to remain compatible with previous implementation
1002c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood            throw new NullPointerException();
1003c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood        }
1004c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // first check for permission to the provider
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // and check for ACCESS_LOCATION_EXTRA_COMMANDS
1008b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood        if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10132f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
1014d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            LocationProviderInterface p = mProvidersByName.get(provider);
1015d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            if (p == null) {
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            return p.sendExtraCommand(command, extras);
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
102322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    public boolean sendNiResponse(int notifId, int userResponse)
102422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    {
102518ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood        if (Binder.getCallingUid() != Process.myUid()) {
102618ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood            throw new SecurityException(
102718ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood                    "calling sendNiResponse from outside of the system is not allowed");
102818ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood        }
102922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        try {
103022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
103122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        }
103222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        catch (RemoteException e)
103322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        {
103422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            Log.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
103522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            return false;
103622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        }
103722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    }
103822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class ProximityAlert {
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int  mUid;
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final double mLatitude;
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final double mLongitude;
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float mRadius;
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final long mExpiration;
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final PendingIntent mIntent;
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Location mLocation;
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ProximityAlert(int uid, double latitude, double longitude,
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float radius, long expiration, PendingIntent intent) {
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mUid = uid;
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLatitude = latitude;
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLongitude = longitude;
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRadius = radius;
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExpiration = expiration;
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIntent = intent;
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocation = new Location("");
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocation.setLatitude(latitude);
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocation.setLongitude(longitude);
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long getExpiration() {
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mExpiration;
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PendingIntent getIntent() {
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mIntent;
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10702d2078aa1d6e31063f565a20b717f3b8908fff02Yusuf T. Mobile        boolean isInProximity(double latitude, double longitude, float accuracy) {
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Location loc = new Location("");
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            loc.setLatitude(latitude);
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            loc.setLongitude(longitude);
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            double radius = loc.distanceTo(mLocation);
10762d2078aa1d6e31063f565a20b717f3b8908fff02Yusuf T. Mobile            return radius <= Math.max(mRadius,accuracy);
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "ProximityAlert{"
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Integer.toHexString(System.identityHashCode(this))
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " uid " + mUid + mIntent + "}";
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void dump(PrintWriter pw, String prefix) {
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + this);
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mLatitude=" + mLatitude + " mLongitude=" + mLongitude);
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mRadius=" + mRadius + " mExpiration=" + mExpiration);
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mIntent=" + mIntent);
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mLocation:");
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocation.dump(new PrintWriterPrinter(pw), prefix + "  ");
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Listener for receiving locations to trigger proximity alerts
109748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    class ProximityListener extends ILocationListener.Stub implements PendingIntent.OnFinished {
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean isGpsAvailable = false;
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Note: this is called with the lock held.
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onLocationChanged(Location loc) {
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If Gps is available, then ignore updates from NetworkLocationProvider
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (loc.getProvider().equals(LocationManager.GPS_PROVIDER)) {
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                isGpsAvailable = true;
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isGpsAvailable && loc.getProvider().equals(LocationManager.NETWORK_PROVIDER)) {
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Process proximity alerts
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long now = System.currentTimeMillis();
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            double latitude = loc.getLatitude();
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            double longitude = loc.getLongitude();
11162d2078aa1d6e31063f565a20b717f3b8908fff02Yusuf T. Mobile            float accuracy = loc.getAccuracy();
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<PendingIntent> intentsToRemove = null;
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (ProximityAlert alert : mProximityAlerts.values()) {
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PendingIntent intent = alert.getIntent();
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long expiration = alert.getExpiration();
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((expiration == -1) || (now <= expiration)) {
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    boolean entered = mProximitiesEntered.contains(alert);
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    boolean inProximity =
11262d2078aa1d6e31063f565a20b717f3b8908fff02Yusuf T. Mobile                        alert.isInProximity(latitude, longitude, accuracy);
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!entered && inProximity) {
1128105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        if (LOCAL_LOGV) {
1129105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                            Log.v(TAG, "Entered alert");
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mProximitiesEntered.add(alert);
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Intent enteredIntent = new Intent();
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        enteredIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, true);
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        try {
11350528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                            synchronized (this) {
11360528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                                // synchronize to ensure incrementPendingBroadcasts()
113748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // is called before decrementPendingBroadcasts()
113848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                intent.send(mContext, 0, enteredIntent, this, mLocationHandler);
113948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // call this after broadcasting so we do not increment
114048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // if we throw an exeption.
11410528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                                incrementPendingBroadcasts();
114248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            }
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } catch (PendingIntent.CanceledException e) {
1144105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                            if (LOCAL_LOGV) {
1145105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                                Log.v(TAG, "Canceled proximity alert: " + alert, e);
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (intentsToRemove == null) {
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                intentsToRemove = new ArrayList<PendingIntent>();
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            intentsToRemove.add(intent);
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else if (entered && !inProximity) {
1153105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        if (LOCAL_LOGV) {
1154105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                            Log.v(TAG, "Exited alert");
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mProximitiesEntered.remove(alert);
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Intent exitedIntent = new Intent();
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        exitedIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, false);
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        try {
11600528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                            synchronized (this) {
11610528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                                // synchronize to ensure incrementPendingBroadcasts()
116248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // is called before decrementPendingBroadcasts()
116348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                intent.send(mContext, 0, exitedIntent, this, mLocationHandler);
116448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // call this after broadcasting so we do not increment
116548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // if we throw an exeption.
11660528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                                incrementPendingBroadcasts();
116748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            }
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } catch (PendingIntent.CanceledException e) {
1169105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                            if (LOCAL_LOGV) {
1170105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                                Log.v(TAG, "Canceled proximity alert: " + alert, e);
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (intentsToRemove == null) {
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                intentsToRemove = new ArrayList<PendingIntent>();
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            intentsToRemove.add(intent);
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Mark alert for expiration
1180105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    if (LOCAL_LOGV) {
1181105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        Log.v(TAG, "Expiring proximity alert: " + alert);
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (intentsToRemove == null) {
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        intentsToRemove = new ArrayList<PendingIntent>();
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    intentsToRemove.add(alert.getIntent());
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Remove expired alerts
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (intentsToRemove != null) {
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (PendingIntent i : intentsToRemove) {
11930dac8c0f7ec00d94b09f92823fa238142163aba8Mike Lockwood                    ProximityAlert alert = mProximityAlerts.remove(i);
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mProximitiesEntered.remove(alert);
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Note: this is called with the lock held.
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onProviderDisabled(String provider) {
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (provider.equals(LocationManager.GPS_PROVIDER)) {
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                isGpsAvailable = false;
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Note: this is called with the lock held.
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onProviderEnabled(String provider) {
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ignore
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Note: this is called with the lock held.
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onStatusChanged(String provider, int status, Bundle extras) {
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((provider.equals(LocationManager.GPS_PROVIDER)) &&
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (status != LocationProvider.AVAILABLE)) {
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                isGpsAvailable = false;
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
121848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
121948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        public void onSendFinished(PendingIntent pendingIntent, Intent intent,
122048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                int resultCode, String resultData, Bundle resultExtras) {
12210528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            // synchronize to ensure incrementPendingBroadcasts()
12220528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            // is called before decrementPendingBroadcasts()
12230528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            synchronized (this) {
12240528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                decrementPendingBroadcasts();
12250528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
122648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addProximityAlert(double latitude, double longitude,
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float radius, long expiration, PendingIntent intent) {
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
12322f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                addProximityAlertLocked(latitude, longitude, radius, expiration, intent);
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "addProximityAlert got exception:", e);
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void addProximityAlertLocked(double latitude, double longitude,
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float radius, long expiration, PendingIntent intent) {
1244105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
1245105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "addProximityAlert: latitude = " + latitude +
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ", longitude = " + longitude +
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ", expiration = " + expiration +
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ", intent = " + intent);
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Require ability to access all providers for now
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isAllowedProviderSafe(LocationManager.GPS_PROVIDER) ||
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            !isAllowedProviderSafe(LocationManager.NETWORK_PROVIDER)) {
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (expiration != -1) {
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            expiration += System.currentTimeMillis();
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ProximityAlert alert = new ProximityAlert(Binder.getCallingUid(),
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                latitude, longitude, radius, expiration, intent);
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProximityAlerts.put(intent, alert);
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
126448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        if (mProximityReceiver == null) {
126548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            mProximityListener = new ProximityListener();
126648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            mProximityReceiver = new Receiver(mProximityListener);
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
126895427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            for (int i = mProviders.size() - 1; i >= 0; i--) {
1269d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                LocationProviderInterface provider = mProviders.get(i);
127048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver);
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeProximityAlert(PendingIntent intent) {
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
12772f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               removeProximityAlertLocked(intent);
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "removeProximityAlert got exception:", e);
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void removeProximityAlertLocked(PendingIntent intent) {
1288105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
1289105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "removeProximityAlert: intent = " + intent);
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProximityAlerts.remove(intent);
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mProximityAlerts.size() == 0) {
129448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            removeUpdatesLocked(mProximityReceiver);
129548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            mProximityReceiver = null;
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProximityListener = null;
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     }
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1301628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood     * @return null if the provider does not exist
1302f2db9fb0f877057a9ef56908d54f3c95fc3fd552Alexey Tarasov     * @throws SecurityException if the provider is not allowed to be
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * accessed by the caller
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Bundle getProviderInfo(String provider) {
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
13072f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _getProviderInfoLocked(provider);
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "_getProviderInfo got exception:", e);
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Bundle _getProviderInfoLocked(String provider) {
1319d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
1320628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood        if (p == null || !p.isEnabled()) {
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bundle b = new Bundle();
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("network", p.requiresNetwork());
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("satellite", p.requiresSatellite());
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("cell", p.requiresCell());
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("cost", p.hasMonetaryCost());
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("altitude", p.supportsAltitude());
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("speed", p.supportsSpeed());
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("bearing", p.supportsBearing());
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putInt("power", p.getPowerRequirement());
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putInt("accuracy", p.getAccuracy());
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return b;
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isProviderEnabled(String provider) {
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
13422f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _isProviderEnabledLocked(provider);
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "isProviderEnabled got exception:", e);
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1353a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood    public void reportLocation(Location location, boolean passive) {
1354275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
1355275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood                != PackageManager.PERMISSION_GRANTED) {
1356275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood            throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
1357275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        }
1358275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood
13594e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location);
13604e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location);
1361a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        m.arg1 = (passive ? 1 : 0);
13624e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        mLocationHandler.sendMessageAtFrontOfQueue(m);
13634e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    }
13644e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood
13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean _isProviderEnabledLocked(String provider) {
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1368d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("provider=" + provider);
13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return isAllowedBySettingsLocked(provider);
13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Location getLastKnownLocation(String provider) {
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
13772f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _getLastKnownLocationLocked(provider);
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "getLastKnownLocation got exception:", e);
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Location _getLastKnownLocationLocked(String provider) {
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1391d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("provider=" + provider);
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isAllowedBySettingsLocked(provider)) {
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14009aa1fa2d3612d1d8ffeae6552d65669f4ca194d9Mike Lockwood        return mLastKnownLocation.get(provider);
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean shouldBroadcastSafe(Location loc, Location lastLoc, UpdateRecord record) {
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Always broadcast the first update
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (lastLoc == null) {
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Don't broadcast same location again regardless of condition
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO - we should probably still rebroadcast if user explicitly sets a minTime > 0
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (loc.getTime() == lastLoc.getTime()) {
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Check whether sufficient distance has been traveled
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        double minDistance = record.mMinDistance;
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (minDistance > 0.0) {
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (loc.distanceTo(lastLoc) <= minDistance) {
14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1426a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood    private void handleLocationChangedLocked(Location location, boolean passive) {
1427a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (records == null || records.size() == 0) {
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1433d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14384e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        // Update last known location for provider
14394e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        Location lastLocation = mLastKnownLocation.get(provider);
14404e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        if (lastLocation == null) {
14414e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood            mLastKnownLocation.put(provider, new Location(location));
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14434e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood            lastLocation.set(location);
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Fetch latest status update time
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long newStatusUpdateTime = p.getStatusUpdateTime();
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14497ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood       // Get latest status
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bundle extras = new Bundle();
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int status = p.getStatus(extras);
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<Receiver> deadReceivers = null;
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Broadcast location or status to all listeners
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = records.size();
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0; i<N; i++) {
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            UpdateRecord r = records.get(i);
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Receiver receiver = r.mReceiver;
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14612f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            Location lastLoc = r.mLastFixBroadcast;
14624e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood            if ((lastLoc == null) || shouldBroadcastSafe(location, lastLoc, r)) {
14634e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                if (lastLoc == null) {
14644e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    lastLoc = new Location(location);
14652f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    r.mLastFixBroadcast = lastLoc;
14664e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                } else {
14674e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    lastLoc.set(location);
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14694e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                if (!receiver.callLocationChangedLocked(location)) {
14704e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    Log.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
14714e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    if (deadReceivers == null) {
14724e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                        deadReceivers = new ArrayList<Receiver>();
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
14744e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    deadReceivers.add(receiver);
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14782f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            long prevStatusUpdateTime = r.mLastStatusBroadcast;
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((newStatusUpdateTime > prevStatusUpdateTime) &&
14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14822f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                r.mLastStatusBroadcast = newStatusUpdateTime;
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!receiver.callStatusChangedLocked(provider, status, extras)) {
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (deadReceivers == null) {
14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        deadReceivers = new ArrayList<Receiver>();
14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!deadReceivers.contains(receiver)) {
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        deadReceivers.add(receiver);
14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (deadReceivers != null) {
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=deadReceivers.size()-1; i>=0; i--) {
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeUpdatesLocked(deadReceivers.get(i));
14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class LocationWorkerHandler extends Handler {
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void handleMessage(Message msg) {
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
15074e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                if (msg.what == MESSAGE_LOCATION_CHANGED) {
15084e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    // log("LocationWorkerHandler: MESSAGE_LOCATION_CHANGED!");
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15102f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    synchronized (mLock) {
15114e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                        Location location = (Location) msg.obj;
1512fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                        String provider = location.getProvider();
1513a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                        boolean passive = (msg.arg1 == 1);
1514a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood
1515a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                        if (!passive) {
1516a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                            // notify other providers of the new location
1517a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                            for (int i = mProviders.size() - 1; i >= 0; i--) {
1518a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                                LocationProviderInterface p = mProviders.get(i);
1519a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                                if (!provider.equals(p.getName())) {
1520a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                                    p.updateLocation(location);
1521a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                                }
152298cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood                            }
152398cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood                        }
152498cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood
1525fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                        if (isAllowedBySettingsLocked(provider)) {
1526a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood                            handleLocationChangedLocked(location, passive);
15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (Exception e) {
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Log, don't crash!
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.e(TAG, "Exception in LocationWorkerHandler.handleMessage:", e);
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15370528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
15380528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        @Override
15390528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        public void onReceive(Context context, Intent intent) {
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String action = intent.getAction();
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15420528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
154308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    || action.equals(Intent.ACTION_PACKAGE_RESTARTED)
1544b56ae20b22fd7283df32072a431ab6d4965f3c1bSuchi Amalapurapu                    || action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
15452f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                synchronized (mLock) {
154608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    int uidList[] = null;
1547b56ae20b22fd7283df32072a431ab6d4965f3c1bSuchi Amalapurapu                    if (action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
154808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        uidList = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
154908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    } else {
155008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        uidList = new int[]{intent.getIntExtra(Intent.EXTRA_UID, -1)};
155108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    }
155208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    if (uidList == null || uidList.length == 0) {
155308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        return;
155408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    }
155508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    for (int uid : uidList) {
155608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        if (uid >= 0) {
155708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            ArrayList<Receiver> removedRecs = null;
155808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            for (ArrayList<UpdateRecord> i : mRecordsByProvider.values()) {
155908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                for (int j=i.size()-1; j>=0; j--) {
156008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    UpdateRecord ur = i.get(j);
156108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    if (ur.mReceiver.isPendingIntent() && ur.mUid == uid) {
156208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                        if (removedRecs == null) {
156308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                            removedRecs = new ArrayList<Receiver>();
156408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                        }
156508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                        if (!removedRecs.contains(ur.mReceiver)) {
156608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                            removedRecs.add(ur.mReceiver);
156708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                        }
15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    }
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
157108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            ArrayList<ProximityAlert> removedAlerts = null;
157208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            for (ProximityAlert i : mProximityAlerts.values()) {
157308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                if (i.mUid == uid) {
157408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    if (removedAlerts == null) {
157508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                        removedAlerts = new ArrayList<ProximityAlert>();
157608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    }
157708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    if (!removedAlerts.contains(i)) {
157808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                        removedAlerts.add(i);
157908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    }
15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
158208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            if (removedRecs != null) {
158308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                for (int i=removedRecs.size()-1; i>=0; i--) {
158408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    removeUpdatesLocked(removedRecs.get(i));
158508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                }
15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
158708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            if (removedAlerts != null) {
158808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                for (int i=removedAlerts.size()-1; i>=0; i--) {
158908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    removeProximityAlertLocked(removedAlerts.get(i).mIntent);
159008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                }
15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15950528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean noConnectivity =
15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!noConnectivity) {
15994df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    mNetworkState = LocationProvider.AVAILABLE;
16004df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                } else {
16014df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
160303d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                NetworkInfo info =
160408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    (NetworkInfo)intent.getExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Notify location providers of current network state
16072f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                synchronized (mLock) {
160815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    for (int i = mProviders.size() - 1; i >= 0; i--) {
1609d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                        LocationProviderInterface provider = mProviders.get(i);
1610628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                        if (provider.isEnabled() && provider.requiresNetwork()) {
161103d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                            provider.updateNetworkState(mNetworkState, info);
16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16170528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    };
16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Wake locks
16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16210528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private void incrementPendingBroadcasts() {
16220528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        synchronized (mWakeLock) {
16230528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (mPendingBroadcasts++ == 0) {
16240528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                try {
16250528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    mWakeLock.acquire();
16260528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    log("Acquired wakelock");
16270528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                } catch (Exception e) {
16280528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // This is to catch a runtime exception thrown when we try to release an
16290528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // already released lock.
16300528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    Log.e(TAG, "exception in acquireWakeLock()", e);
16310528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                }
16320528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
163348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
163448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
163548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
163648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private void decrementPendingBroadcasts() {
16370528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        synchronized (mWakeLock) {
163848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (--mPendingBroadcasts == 0) {
16390528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                try {
16400528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // Release wake lock
16410528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    if (mWakeLock.isHeld()) {
16420528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                        mWakeLock.release();
16430528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                        log("Released wakelock");
16440528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    } else {
16450528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                        log("Can't release wakelock again!");
16460528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    }
16470528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                } catch (Exception e) {
16480528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // This is to catch a runtime exception thrown when we try to release an
16490528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // already released lock.
16500528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    Log.e(TAG, "exception in releaseWakeLock()", e);
16510528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                }
165248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
165348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
165448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
165548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Geocoder
16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String getFromLocation(double latitude, double longitude, int maxResults,
165934901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwood            GeocoderParams params, List<Address> addrs) {
1660a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        if (mGeocodeProvider != null) {
1661628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood            return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
1662628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                    params, addrs);
16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1664a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        return null;
16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1667a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String getFromLocationName(String locationName,
1669a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            double lowerLeftLatitude, double lowerLeftLongitude,
1670a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            double upperRightLatitude, double upperRightLongitude, int maxResults,
167134901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwood            GeocoderParams params, List<Address> addrs) {
1672a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood
1673a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        if (mGeocodeProvider != null) {
1674628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood            return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
1675628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                    lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
1676628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                    maxResults, params, addrs);
16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1678a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        return null;
16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Mock Providers
16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void checkMockPermissionsSafe() {
16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(),
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1;
16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!allowMocks) {
16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting");
16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) !=
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PackageManager.PERMISSION_GRANTED) {
16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission");
16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite,
16979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1701a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
1702a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood            throw new IllegalArgumentException("Cannot mock the passive location provider");
1703a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        }
1704a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood
170586328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood        long identity = Binder.clearCallingIdentity();
17062f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
17074e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood            MockProvider provider = new MockProvider(name, this,
17084e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                requiresNetwork, requiresSatellite,
17099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                requiresCell, hasMonetaryCost, supportsAltitude,
17109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                supportsSpeed, supportsBearing, powerRequirement, accuracy);
17117566c1debebe072af76411e11d96810fd1409482Mike Lockwood            // remove the real provider if we are replacing GPS or network provider
17127566c1debebe072af76411e11d96810fd1409482Mike Lockwood            if (LocationManager.GPS_PROVIDER.equals(name)
17137566c1debebe072af76411e11d96810fd1409482Mike Lockwood                    || LocationManager.NETWORK_PROVIDER.equals(name)) {
1714d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                LocationProviderInterface p = mProvidersByName.get(name);
1715d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                if (p != null) {
1716d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                    p.enableLocationTracking(false);
1717d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                    removeProvider(p);
17187566c1debebe072af76411e11d96810fd1409482Mike Lockwood                }
17197566c1debebe072af76411e11d96810fd1409482Mike Lockwood            }
172015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (mProvidersByName.get(name) != null) {
17219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
17229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1723d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            addProvider(provider);
17247ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mMockProviders.put(name, provider);
17257566c1debebe072af76411e11d96810fd1409482Mike Lockwood            mLastKnownLocation.put(name, null);
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
17279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
172886328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood        Binder.restoreCallingIdentity(identity);
17299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeTestProvider(String provider) {
17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17332f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
17347ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
17357ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
17369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
17379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
173886328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            long identity = Binder.clearCallingIdentity();
173915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            removeProvider(mProvidersByName.get(provider));
17407ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mMockProviders.remove(mockProvider);
17417566c1debebe072af76411e11d96810fd1409482Mike Lockwood            // reinstall real provider if we were mocking GPS or network provider
17427566c1debebe072af76411e11d96810fd1409482Mike Lockwood            if (LocationManager.GPS_PROVIDER.equals(provider) &&
17437566c1debebe072af76411e11d96810fd1409482Mike Lockwood                    mGpsLocationProvider != null) {
17447566c1debebe072af76411e11d96810fd1409482Mike Lockwood                addProvider(mGpsLocationProvider);
17457566c1debebe072af76411e11d96810fd1409482Mike Lockwood            } else if (LocationManager.NETWORK_PROVIDER.equals(provider) &&
17467566c1debebe072af76411e11d96810fd1409482Mike Lockwood                    mNetworkLocationProvider != null) {
17477566c1debebe072af76411e11d96810fd1409482Mike Lockwood                addProvider(mNetworkLocationProvider);
17487566c1debebe072af76411e11d96810fd1409482Mike Lockwood            }
17497566c1debebe072af76411e11d96810fd1409482Mike Lockwood            mLastKnownLocation.put(provider, null);
17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
175186328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            Binder.restoreCallingIdentity(identity);
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderLocation(String provider, Location loc) {
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17572f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
17587ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
17597ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
176295427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
176395427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            long identity = Binder.clearCallingIdentity();
17647ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.setLocation(loc);
176595427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            Binder.restoreCallingIdentity(identity);
17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderLocation(String provider) {
17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17712f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
17727ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
17737ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17767ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.clearLocation();
17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderEnabled(String provider, boolean enabled) {
17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17822f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
17837ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
17847ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
178786328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            long identity = Binder.clearCallingIdentity();
17889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (enabled) {
17897ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                mockProvider.enable();
17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEnabledProviders.add(provider);
17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDisabledProviders.remove(provider);
17929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
17937ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                mockProvider.disable();
17949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEnabledProviders.remove(provider);
17959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDisabledProviders.add(provider);
17969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
179886328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            Binder.restoreCallingIdentity(identity);
17999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderEnabled(String provider) {
18039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18042f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18057ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18067ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
180986328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            long identity = Binder.clearCallingIdentity();
18109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEnabledProviders.remove(provider);
18119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDisabledProviders.remove(provider);
18129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
181386328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            Binder.restoreCallingIdentity(identity);
18149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
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            }
18247ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.setStatus(status, extras, updateTime);
18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderStatus(String provider) {
18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18302f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18317ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18327ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18357ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.clearStatus();
18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void log(String log) {
18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Log.isLoggable(TAG, Log.VERBOSE)) {
18419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.d(TAG, log);
18429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
18469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
18479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
18480528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            pw.println("Permission Denial: can't dump LocationManagerService from from pid="
18499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Binder.getCallingPid()
18509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", uid=" + Binder.getCallingUid());
18519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
18529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18542f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("Current Location Manager state:");
18569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  sProvidersLoaded=" + sProvidersLoaded);
18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Listeners:");
18582f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            int N = mReceivers.size();
18599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
18602f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                pw.println("    " + mReceivers.get(i));
18619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Location Listeners:");
18632f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            for (Receiver i : mReceivers.values()) {
18642f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                pw.println("    " + i + ":");
18652f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                for (Map.Entry<String,UpdateRecord> j : i.mUpdateRecords.entrySet()) {
18669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("      " + j.getKey() + ":");
18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    j.getValue().dump(pw, "        ");
18689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
18699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Records by Provider:");
18719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (Map.Entry<String, ArrayList<UpdateRecord>> i
18729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    : mRecordsByProvider.entrySet()) {
18739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("    " + i.getKey() + ":");
18749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (UpdateRecord j : i.getValue()) {
18759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("      " + j + ":");
18769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    j.dump(pw, "        ");
18779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
18789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Last Known Locations:");
18809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (Map.Entry<String, Location> i
18819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    : mLastKnownLocation.entrySet()) {
18829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("    " + i.getKey() + ":");
18839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                i.getValue().dump(new PrintWriterPrinter(pw), "      ");
18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mProximityAlerts.size() > 0) {
18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Proximity Alerts:");
18879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (Map.Entry<PendingIntent, ProximityAlert> i
18889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        : mProximityAlerts.entrySet()) {
18899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i.getKey() + ":");
18909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    i.getValue().dump(pw, "      ");
18919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
18929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mProximitiesEntered.size() > 0) {
18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Proximities Entered:");
18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (ProximityAlert i : mProximitiesEntered) {
18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i + ":");
18979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    i.dump(pw, "      ");
18989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
18999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
190048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            pw.println("  mProximityReceiver=" + mProximityReceiver);
19019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  mProximityListener=" + mProximityListener);
19029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mEnabledProviders.size() > 0) {
19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Enabled Providers:");
19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (String i : mEnabledProviders) {
19059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i);
19069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mDisabledProviders.size() > 0) {
19109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Disabled Providers:");
19119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (String i : mDisabledProviders) {
19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i);
19139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mMockProviders.size() > 0) {
19179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Mock Providers:");
19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
19197ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                    i.getValue().dump(pw, "      ");
19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1925