LocationManagerService.java revision 08675a3376819a82aa5ab344bc3e7b1635c30b05
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashSet;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map;
269637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwoodimport java.util.Observable;
279637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwoodimport java.util.Observer;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.PendingIntent;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver;
329637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwoodimport android.content.ContentQueryMap;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
389637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwoodimport android.database.Cursor;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Address;
4034901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwoodimport android.location.GeocoderParams;
41a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwoodimport android.location.IGeocodeProvider;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.IGpsStatusListener;
4315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwoodimport android.location.IGpsStatusProvider;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.ILocationListener;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.ILocationManager;
46e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwoodimport android.location.ILocationProvider;
4722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport android.location.INetInitiatedListener;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Location;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationManager;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationProvider;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.ConnectivityManager;
5203d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwoodimport android.net.NetworkInfo;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
583d12b51ee38537f6760a833618948f936e75561dMike Lockwoodimport android.os.Looper;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager;
61e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwoodimport android.os.Process;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.PrintWriterPrinter;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.location.GpsLocationProvider;
68e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwoodimport com.android.internal.location.LocationProviderProxy;
697ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwoodimport com.android.internal.location.MockProvider;
7022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport com.android.internal.location.GpsNetInitiatedHandler;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The service class that manages LocationProviders and issues location
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * updates and alerts.
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
783d12b51ee38537f6760a833618948f936e75561dMike Lockwoodpublic class LocationManagerService extends ILocationManager.Stub implements Runnable {
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "LocationManagerService";
80105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private static final boolean LOCAL_LOGV = false;
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // The last time a location was written, by provider name.
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<String,Long> mLastWriteTime = new HashMap<String,Long>();
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_FINE_LOCATION =
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        android.Manifest.permission.ACCESS_FINE_LOCATION;
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_COARSE_LOCATION =
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        android.Manifest.permission.ACCESS_COARSE_LOCATION;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_MOCK_LOCATION =
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        android.Manifest.permission.ACCESS_MOCK_LOCATION;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
93275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood    private static final String INSTALL_LOCATION_PROVIDER =
94275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Set of providers that are explicitly enabled
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Set<String> mEnabledProviders = new HashSet<String>();
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Set of providers that are explicitly disabled
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Set<String> mDisabledProviders = new HashSet<String>();
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Locations, status values, and extras for mock providers
1037ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood    private final HashMap<String,MockProvider> mMockProviders = new HashMap<String,MockProvider>();
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean sProvidersLoaded = false;
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Context mContext;
108a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood    private IGeocodeProvider mGeocodeProvider;
10915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private IGpsStatusProvider mGpsStatusProvider;
11022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private INetInitiatedListener mNetInitiatedListener;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private LocationWorkerHandler mLocationHandler;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1137566c1debebe072af76411e11d96810fd1409482Mike Lockwood    // Cache the real providers for use in addTestProvider() and removeTestProvider()
1147566c1debebe072af76411e11d96810fd1409482Mike Lockwood     LocationProviderProxy mNetworkLocationProvider;
1157566c1debebe072af76411e11d96810fd1409482Mike Lockwood     LocationProviderProxy mGpsLocationProvider;
1167566c1debebe072af76411e11d96810fd1409482Mike Lockwood
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Handler messages
1184e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    private static final int MESSAGE_LOCATION_CHANGED = 1;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1200528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    // wakelock variables
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final static String WAKELOCK_KEY = "LocationManagerService";
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private PowerManager.WakeLock mWakeLock = null;
12348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private int mPendingBroadcasts;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1262f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood     * List of all receivers.
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1282f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final HashMap<Object, Receiver> mReceivers = new HashMap<Object, Receiver>();
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
13115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    /**
13215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood     * List of location providers.
13315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood     */
13415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final ArrayList<LocationProviderProxy> mProviders =
13515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        new ArrayList<LocationProviderProxy>();
13615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private final HashMap<String, LocationProviderProxy> mProvidersByName
13715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        = new HashMap<String, LocationProviderProxy>();
13815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1402f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood     * Object used internally for synchronization
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1422f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final Object mLock = new Object();
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Mapping from provider name to all its UpdateRecords
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final HashMap<String,ArrayList<UpdateRecord>> mRecordsByProvider =
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashMap<String,ArrayList<UpdateRecord>>();
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Proximity listeners
15148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private Receiver mProximityReceiver = null;
15248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private ILocationListener mProximityListener = null;
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<PendingIntent,ProximityAlert> mProximityAlerts =
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashMap<PendingIntent,ProximityAlert>();
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashSet<ProximityAlert> mProximitiesEntered =
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashSet<ProximityAlert>();
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Last known location for each provider
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private HashMap<String,Location> mLastKnownLocation =
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        new HashMap<String,Location>();
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1624df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    private int mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
1634df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
1649637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood    // for Settings change notification
1659637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood    private ContentQueryMap mSettings;
1669637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A wrapper class holding either an ILocationListener or a PendingIntent to receive
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * location updates.
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ILocationListener mListener;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final PendingIntent mPendingIntent;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Object mKey;
1752f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
17648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        int mPendingBroadcasts;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1782f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver(ILocationListener listener) {
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = listener;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPendingIntent = null;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mKey = listener.asBinder();
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1842f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver(PendingIntent intent) {
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPendingIntent = intent;
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = null;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mKey = intent;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean equals(Object otherObj) {
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (otherObj instanceof Receiver) {
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mKey.equals(
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ((Receiver)otherObj).mKey);
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int hashCode() {
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mKey.hashCode();
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2033681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return "Receiver{"
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + Integer.toHexString(System.identityHashCode(this))
2092f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                        + " Listener " + mKey + "}";
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return "Receiver{"
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + Integer.toHexString(System.identityHashCode(this))
2132f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                        + " Intent " + mKey + "}";
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean isListener() {
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mListener != null;
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean isPendingIntent() {
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mPendingIntent != null;
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ILocationListener getListener() {
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mListener;
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("Request for non-existent listener");
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public PendingIntent getPendingIntent() {
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mPendingIntent != null) {
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mPendingIntent;
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("Request for non-existent intent");
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
24248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
24348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
24448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
24548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mListener.onStatusChanged(provider, status, extras);
24648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (mListener != mProximityListener) {
24748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // call this after broadcasting so we do not increment
24848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // if we throw an exeption.
24948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            incrementPendingBroadcastsLocked();
25048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
25148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent statusChanged = new Intent();
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                statusChanged.putExtras(extras);
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
26048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
26148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
26248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
26348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler);
26448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
26548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
26648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
26748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (PendingIntent.CanceledException e) {
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean callLocationChangedLocked(Location location) {
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
27848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
27948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
28048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
28148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mListener.onLocationChanged(location);
28248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (mListener != mProximityListener) {
28348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // call this after broadcasting so we do not increment
28448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // if we throw an exeption.
28548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            incrementPendingBroadcastsLocked();
28648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
28748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent locationChanged = new Intent();
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, location);
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
29548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
29648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
29748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
29848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler);
29948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
30048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
30148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
30248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
30348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                } catch (PendingIntent.CanceledException e) {
30448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    return false;
30548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
30648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
30748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            return true;
30848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
30948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
31048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        public boolean callProviderEnabledLocked(String provider, boolean enabled) {
31148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (mListener != null) {
31248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                try {
31348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
31448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
31548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
31648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (enabled) {
31748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            mListener.onProviderEnabled(provider);
31848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        } else {
31948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            mListener.onProviderDisabled(provider);
32048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
32148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (mListener != mProximityListener) {
32248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // call this after broadcasting so we do not increment
32348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            // if we throw an exeption.
32448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            incrementPendingBroadcastsLocked();
32548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
32648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
32748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                } catch (RemoteException e) {
32848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    return false;
32948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
33048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            } else {
33148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                Intent providerIntent = new Intent();
33248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
33348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                try {
33448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
33548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
33648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
33748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler);
33848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
33948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
34048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
34148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (PendingIntent.CanceledException e) {
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
350105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            if (LOCAL_LOGV) {
351105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                Log.v(TAG, "Location listener died");
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3532f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeUpdatesLocked(this);
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
35648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            synchronized (this) {
35748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                if (mPendingBroadcasts > 0) {
35848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    LocationManagerService.this.decrementPendingBroadcasts();
35948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    mPendingBroadcasts = 0;
36048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
36148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
36248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
36348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
36448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        public void onSendFinished(PendingIntent pendingIntent, Intent intent,
36548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                int resultCode, String resultData, Bundle resultExtras) {
3660528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            synchronized (this) {
3670528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                decrementPendingBroadcastsLocked();
3680528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
36948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
37048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
3710528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // this must be called while synchronized by caller in a synchronized block
37248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        // containing the sending of the broadcaset
37348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        private void incrementPendingBroadcastsLocked() {
37448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (mPendingBroadcasts++ == 0) {
3750528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                LocationManagerService.this.incrementPendingBroadcasts();
37648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
37748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
37848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
3790528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        private void decrementPendingBroadcastsLocked() {
3800528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (--mPendingBroadcasts == 0) {
3810528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                LocationManagerService.this.decrementPendingBroadcasts();
38248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
38348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
38448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
38548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
38648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    public void locationCallbackFinished(ILocationListener listener) {
387080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //Do not use getReceiver here as that will add the ILocationListener to
388080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //the receiver list if it is not found.  If it is not found then the
389080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //LocationListener was removed when it had a pending broadcast and should
390080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //not be added back.
391080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        IBinder binder = listener.asBinder();
392080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        Receiver receiver = mReceivers.get(binder);
39348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        if (receiver != null) {
3940528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            synchronized (receiver) {
3950528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                // so wakelock calls will succeed
3960528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                long identity = Binder.clearCallingIdentity();
3970528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                receiver.decrementPendingBroadcastsLocked();
3980528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                Binder.restoreCallingIdentity(identity);
3990528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood           }
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4039637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood    private final class SettingsObserver implements Observer {
4049637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        public void update(Observable o, Object arg) {
4052f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
4069637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood                updateProvidersLocked();
4079637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood            }
4089637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        }
4099637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood    }
4109637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood
41115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private void addProvider(LocationProviderProxy provider) {
41215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProviders.add(provider);
41315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProvidersByName.put(provider.getName(), provider);
41415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
41515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
41615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private void removeProvider(LocationProviderProxy provider) {
41715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProviders.remove(provider);
418fff2fda0199dedbf1079454dca98a81190dce765Suchi Amalapurapu        provider.unlinkProvider();
41915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProvidersByName.remove(provider.getName());
42015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
42115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void loadProviders() {
4232f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sProvidersLoaded) {
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Load providers
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            loadProvidersLocked();
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sProvidersLoaded = true;
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void loadProvidersLocked() {
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            _loadProvidersLocked();
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "Exception loading providers:", e);
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void _loadProvidersLocked() {
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Attempt to load "real" providers first
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (GpsLocationProvider.isSupported()) {
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Create a gps location provider
44615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            GpsLocationProvider provider = new GpsLocationProvider(mContext, this);
44715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            mGpsStatusProvider = provider.getGpsStatusProvider();
44822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            mNetInitiatedListener = provider.getNetInitiatedListener();
4498dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood            LocationProviderProxy proxy = new LocationProviderProxy(LocationManager.GPS_PROVIDER, provider);
4508dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood            addProvider(proxy);
4517566c1debebe072af76411e11d96810fd1409482Mike Lockwood            mGpsLocationProvider = proxy;
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updateProvidersLocked();
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context the context that the LocationManagerService runs in
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public LocationManagerService(Context context) {
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super();
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
4633d12b51ee38537f6760a833618948f936e75561dMike Lockwood
4643d12b51ee38537f6760a833618948f936e75561dMike Lockwood        Thread thread = new Thread(null, this, "LocationManagerService");
4653d12b51ee38537f6760a833618948f936e75561dMike Lockwood        thread.start();
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
467105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
468105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "Constructed LocationManager Service");
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4703d12b51ee38537f6760a833618948f936e75561dMike Lockwood    }
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4723d12b51ee38537f6760a833618948f936e75561dMike Lockwood    private void initialize() {
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Create a wake lock, needs to be done before calling loadProviders() below
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
4760528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Load providers
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        loadProviders();
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Register for Network (Wifi or Mobile) updates
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IntentFilter intentFilter = new IntentFilter();
4820528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
4830528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // Register for Package Manager updates
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
4860528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        mContext.registerReceiver(mBroadcastReceiver, intentFilter);
48708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu        IntentFilter sdFilter = new IntentFilter(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
48808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu        mContext.registerReceiver(mBroadcastReceiver, sdFilter);
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4909637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        // listen for settings changes
4919637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        ContentResolver resolver = mContext.getContentResolver();
4929637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        Cursor settingsCursor = resolver.query(Settings.Secure.CONTENT_URI, null,
4939637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood                "(" + Settings.System.NAME + "=?)",
4949637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood                new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
4959637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood                null);
4969637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mLocationHandler);
4979637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        SettingsObserver settingsObserver = new SettingsObserver();
4989637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood        mSettings.addObserver(settingsObserver);
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5013d12b51ee38537f6760a833618948f936e75561dMike Lockwood    public void run()
5023d12b51ee38537f6760a833618948f936e75561dMike Lockwood    {
5033d12b51ee38537f6760a833618948f936e75561dMike Lockwood        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
5043d12b51ee38537f6760a833618948f936e75561dMike Lockwood        Looper.prepare();
5053d12b51ee38537f6760a833618948f936e75561dMike Lockwood        mLocationHandler = new LocationWorkerHandler();
5063d12b51ee38537f6760a833618948f936e75561dMike Lockwood        initialize();
5073d12b51ee38537f6760a833618948f936e75561dMike Lockwood        Looper.loop();
5083d12b51ee38537f6760a833618948f936e75561dMike Lockwood    }
5093d12b51ee38537f6760a833618948f936e75561dMike Lockwood
510275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood    public void installLocationProvider(String name, ILocationProvider provider) {
511275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
512275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood                != PackageManager.PERMISSION_GRANTED) {
513275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood            throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
514e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwood        }
515e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwood
5162f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
5173681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood            // check to see if we are reinstalling a dead provider
5183681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood            LocationProviderProxy oldProvider = mProvidersByName.get(name);
5193681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood            if (oldProvider != null) {
5203681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood                if (oldProvider.isDead()) {
5213681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood                    Log.d(TAG, "replacing dead provider");
5223681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood                    removeProvider(oldProvider);
5233681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood                } else {
5243681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood                    throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
5253681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood                }
5263681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood            }
5273681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood
5288dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood            LocationProviderProxy proxy = new LocationProviderProxy(name, provider);
5298dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood            addProvider(proxy);
5308dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood            updateProvidersLocked();
5317566c1debebe072af76411e11d96810fd1409482Mike Lockwood            if (LocationManager.NETWORK_PROVIDER.equals(name)) {
5327566c1debebe072af76411e11d96810fd1409482Mike Lockwood                mNetworkLocationProvider = proxy;
5337566c1debebe072af76411e11d96810fd1409482Mike Lockwood            }
534275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood
5358dfe5d8c6ba9cb165994f09843abaa6302d63c1dMike Lockwood            // notify provider of current network state
53603d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood            proxy.updateNetworkState(mNetworkState, null);
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
540275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood    public void installGeocodeProvider(IGeocodeProvider provider) {
541275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
542275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood                != PackageManager.PERMISSION_GRANTED) {
543275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood            throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
544a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        }
545a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood
546a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        mGeocodeProvider = provider;
547a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood    }
548a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean isAllowedBySettingsLocked(String provider) {
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabledProviders.contains(provider)) {
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDisabledProviders.contains(provider)) {
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Use system settings
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ContentResolver resolver = mContext.getContentResolver();
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5598eb3ea659761edc2cd5db3acf448059f19389e5eBrad Larson        return Settings.Secure.isLocationProviderEnabled(resolver, provider);
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void checkPermissionsSafe(String provider) {
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (LocationManager.GPS_PROVIDER.equals(provider)
564b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (LocationManager.NETWORK_PROVIDER.equals(provider)
569b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)
571b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION)
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException(
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "Requires ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission");
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean isAllowedProviderSafe(String provider) {
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (LocationManager.GPS_PROVIDER.equals(provider)
580b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (LocationManager.NETWORK_PROVIDER.equals(provider)
585b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION)
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)
587b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood            && (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION)
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<String> getAllProviders() {
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
5972f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _getAllProvidersLocked();
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "getAllProviders got exception:", e);
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private List<String> _getAllProvidersLocked() {
609105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
610105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "getAllProviders");
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
61215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        ArrayList<String> out = new ArrayList<String>(mProviders.size());
61315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        for (int i = mProviders.size() - 1; i >= 0; i--) {
61415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            LocationProviderProxy p = mProviders.get(i);
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            out.add(p.getName());
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return out;
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<String> getProviders(boolean enabledOnly) {
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
6222f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _getProvidersLocked(enabledOnly);
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
628105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.e(TAG, "getProviders got exception:", e);
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private List<String> _getProvidersLocked(boolean enabledOnly) {
634105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
635105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "getProviders");
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
63715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        ArrayList<String> out = new ArrayList<String>(mProviders.size());
63815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        for (int i = mProviders.size() - 1; i >= 0; i--) {
63915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            LocationProviderProxy p = mProviders.get(i);
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = p.getName();
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isAllowedProviderSafe(name)) {
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (enabledOnly && !isAllowedBySettingsLocked(name)) {
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                out.add(name);
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return out;
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateProvidersLocked() {
65215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        for (int i = mProviders.size() - 1; i >= 0; i--) {
65315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            LocationProviderProxy p = mProviders.get(i);
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean isEnabled = p.isEnabled();
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = p.getName();
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isEnabled && !shouldBeEnabled) {
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                updateProviderListenersLocked(name, false);
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (!isEnabled && shouldBeEnabled) {
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                updateProviderListenersLocked(name, true);
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateProviderListenersLocked(String provider, boolean enabled) {
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int listeners = 0;
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
67015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        LocationProviderProxy p = mProvidersByName.get(provider);
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<Receiver> deadReceivers = null;
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (records != null) {
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int N = records.size();
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                UpdateRecord record = records.get(i);
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Sends a notification message to the receiver
68348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
68448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    if (deadReceivers == null) {
68548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        deadReceivers = new ArrayList<Receiver>();
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6874686657cee6411eb00235d49b4a8663a96361a00Simon Schoar                    deadReceivers.add(record.mReceiver);
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                listeners++;
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (deadReceivers != null) {
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=deadReceivers.size()-1; i>=0; i--) {
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeUpdatesLocked(deadReceivers.get(i));
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (enabled) {
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.enable();
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (listeners > 0) {
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.setMinTime(getMinTimeLocked(provider));
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.enableLocationTracking(true);
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.enableLocationTracking(false);
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.disable();
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long getMinTimeLocked(String provider) {
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long minTime = Long.MAX_VALUE;
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (records != null) {
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=records.size()-1; i>=0; i--) {
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                minTime = Math.min(minTime, records.get(i).mMinTime);
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return minTime;
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class UpdateRecord {
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String mProvider;
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Receiver mReceiver;
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final long mMinTime;
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float mMinDistance;
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int mUid;
7282f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Location mLastFixBroadcast;
7292f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        long mLastStatusBroadcast;
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Note: must be constructed with lock held.
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        UpdateRecord(String provider, long minTime, float minDistance,
7352f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            Receiver receiver, int uid) {
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProvider = provider;
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mReceiver = receiver;
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMinTime = minTime;
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMinDistance = minDistance;
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mUid = uid;
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (records == null) {
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                records = new ArrayList<UpdateRecord>();
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRecordsByProvider.put(provider, records);
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!records.contains(this)) {
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                records.add(this);
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Method to be called when a record will no longer be used.  Calling this multiple times
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * must have the same effect as calling it once.
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void disposeLocked() {
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<UpdateRecord> records = mRecordsByProvider.get(this.mProvider);
7583a76fd627945c1df59aa0318867401e0e53da022Mike Lockwood            if (records != null) {
7593a76fd627945c1df59aa0318867401e0e53da022Mike Lockwood                records.remove(this);
7603a76fd627945c1df59aa0318867401e0e53da022Mike Lockwood            }
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "UpdateRecord{"
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Integer.toHexString(System.identityHashCode(this))
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " " + mProvider + " " + mReceiver + "}";
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void dump(PrintWriter pw, String prefix) {
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + this);
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mProvider=" + mProvider + " mReceiver=" + mReceiver);
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mMinTime=" + mMinTime + " mMinDistance=" + mMinDistance);
7742f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            pw.println(prefix + "mUid=" + mUid);
7752f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            pw.println(prefix + "mLastFixBroadcast:");
7762f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            mLastFixBroadcast.dump(new PrintWriterPrinter(pw), prefix + "  ");
7772f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            pw.println(prefix + "mLastStatusBroadcast=" + mLastStatusBroadcast);
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7812f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private Receiver getReceiver(ILocationListener listener) {
7822f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        IBinder binder = listener.asBinder();
7832f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver receiver = mReceivers.get(binder);
7842f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (receiver == null) {
7852f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            receiver = new Receiver(listener);
7862f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            mReceivers.put(binder, receiver);
7872f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
7882f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            try {
7892f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                if (receiver.isListener()) {
7902f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    receiver.getListener().asBinder().linkToDeath(receiver, 0);
7912f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                }
7922f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            } catch (RemoteException e) {
7932f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                Log.e(TAG, "linkToDeath failed:", e);
7942f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                return null;
7952f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
7962f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
7972f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        return receiver;
7982f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
7992f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8002f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private Receiver getReceiver(PendingIntent intent) {
8012f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver receiver = mReceivers.get(intent);
8022f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (receiver == null) {
8032f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            receiver = new Receiver(intent);
8042f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            mReceivers.put(intent, receiver);
8052f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
8062f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        return receiver;
8072f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
8082f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8092f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private boolean providerHasListener(String provider, int uid, Receiver excludedReceiver) {
8102f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
8112f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (records != null) {
8122f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            for (int i = records.size() - 1; i >= 0; i--) {
8132f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                UpdateRecord record = records.get(i);
8142f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                if (record.mUid == uid && record.mReceiver != excludedReceiver) {
8152f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    return true;
8162f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                }
8172f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood           }
8182f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
81995427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood        for (ProximityAlert alert : mProximityAlerts.values()) {
82095427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            if (alert.mUid == uid) {
82195427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood                return true;
8222f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
8232f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
8242f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        return false;
8252f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
8262f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void requestLocationUpdates(String provider,
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long minTime, float minDistance, ILocationListener listener) {
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8312f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
8322f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                requestLocationUpdatesLocked(provider, minTime, minDistance, getReceiver(listener));
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "requestUpdates got exception:", e);
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void requestLocationUpdatesPI(String provider,
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long minTime, float minDistance, PendingIntent intent) {
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8442f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
8452f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                requestLocationUpdatesLocked(provider, minTime, minDistance, getReceiver(intent));
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "requestUpdates got exception:", e);
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void requestLocationUpdatesLocked(String provider,
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long minTime, float minDistance, Receiver receiver) {
856105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
857105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "_requestLocationUpdates: listener = " + receiver);
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
86015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        LocationProviderProxy proxy = mProvidersByName.get(provider);
86115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (proxy == null) {
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("provider=" + provider);
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // so wakelock calls will succeed
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int callingUid = Binder.getCallingUid();
8692f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        boolean newUid = !providerHasListener(provider, callingUid, null);
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identity = Binder.clearCallingIdentity();
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8722f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            UpdateRecord r = new UpdateRecord(provider, minTime, minDistance, receiver, callingUid);
8732f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            UpdateRecord oldRecord = receiver.mUpdateRecords.put(provider, r);
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (oldRecord != null) {
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                oldRecord.disposeLocked();
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8782f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            if (newUid) {
87915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                proxy.addListener(callingUid);
8802f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
8812f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean isProviderEnabled = isAllowedBySettingsLocked(provider);
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isProviderEnabled) {
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long minTimeForProvider = getMinTimeLocked(provider);
88515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                proxy.setMinTime(minTimeForProvider);
88615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                proxy.enableLocationTracking(true);
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
88848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                // Notify the listener that updates are currently disabled
88948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                receiver.callProviderEnabledLocked(provider, false);
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(identity);
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeUpdates(ILocationListener listener) {
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8982f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
8992f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                removeUpdatesLocked(getReceiver(listener));
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "removeUpdates got exception:", e);
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeUpdatesPI(PendingIntent intent) {
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
9102f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
9112f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                removeUpdatesLocked(getReceiver(intent));
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "removeUpdates got exception:", e);
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void removeUpdatesLocked(Receiver receiver) {
921105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
922105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "_removeUpdates: listener = " + receiver);
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // so wakelock calls will succeed
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int callingUid = Binder.getCallingUid();
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identity = Binder.clearCallingIdentity();
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
9292f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
9302f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
931080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                synchronized(receiver) {
932080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                    if(receiver.mPendingBroadcasts > 0) {
933080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                        decrementPendingBroadcasts();
934080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                        receiver.mPendingBroadcasts = 0;
935080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                    }
936080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                }
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Record which providers were associated with this listener
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            HashSet<String> providers = new HashSet<String>();
9412f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            HashMap<String,UpdateRecord> oldRecords = receiver.mUpdateRecords;
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (oldRecords != null) {
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Call dispose() on the obsolete update records.
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (UpdateRecord record : oldRecords.values()) {
9452f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    if (!providerHasListener(record.mProvider, callingUid, receiver)) {
94615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        LocationProviderProxy proxy = mProvidersByName.get(record.mProvider);
94715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        if (proxy != null) {
94815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                            proxy.removeListener(callingUid);
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    record.disposeLocked();
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Accumulate providers
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                providers.addAll(oldRecords.keySet());
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // See if the providers associated with this listener have any
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // other listeners; if one does, inform it of the new smallest minTime
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // value; if one does not, disable location tracking for it
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (String provider : providers) {
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // If provider is already disabled, don't need to do anything
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!isAllowedBySettingsLocked(provider)) {
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean hasOtherListener = false;
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ArrayList<UpdateRecord> recordsForProvider = mRecordsByProvider.get(provider);
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (recordsForProvider != null && recordsForProvider.size() > 0) {
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    hasOtherListener = true;
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
97215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                LocationProviderProxy p = mProvidersByName.get(provider);
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (p != null) {
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (hasOtherListener) {
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        p.setMinTime(getMinTimeLocked(provider));
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        p.enableLocationTracking(false);
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(identity);
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean addGpsStatusListener(IGpsStatusListener listener) {
98715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mGpsStatusProvider == null) {
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
990b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood        if (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) !=
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PackageManager.PERMISSION_GRANTED) {
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
99615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            mGpsStatusProvider.addGpsStatusListener(listener);
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
99815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            Log.e(TAG, "mGpsStatusProvider.addGpsStatusListener failed", e);
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeGpsStatusListener(IGpsStatusListener listener) {
10052f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
100615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            try {
100715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                mGpsStatusProvider.removeGpsStatusListener(listener);
100815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            } catch (Exception e) {
100915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                Log.e(TAG, "mGpsStatusProvider.removeGpsStatusListener failed", e);
101015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendExtraCommand(String provider, String command, Bundle extras) {
1015c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood        if (provider == null) {
1016c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood            // throw NullPointerException to remain compatible with previous implementation
1017c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood            throw new NullPointerException();
1018c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood        }
1019c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // first check for permission to the provider
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // and check for ACCESS_LOCATION_EXTRA_COMMANDS
1023b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood        if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10282f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
102915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            LocationProviderProxy proxy = mProvidersByName.get(provider);
10306ba7ae1e4c3c04f6a71380b913ad79f83b00a628Mike Lockwood            if (proxy == null) {
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
103415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            return proxy.sendExtraCommand(command, extras);
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
103822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    public boolean sendNiResponse(int notifId, int userResponse)
103922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    {
104018ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood        if (Binder.getCallingUid() != Process.myUid()) {
104118ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood            throw new SecurityException(
104218ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood                    "calling sendNiResponse from outside of the system is not allowed");
104318ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood        }
104422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        try {
104522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
104622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        }
104722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        catch (RemoteException e)
104822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        {
104922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            Log.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
105022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            return false;
105122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        }
105222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    }
105322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class ProximityAlert {
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int  mUid;
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final double mLatitude;
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final double mLongitude;
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float mRadius;
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final long mExpiration;
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final PendingIntent mIntent;
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Location mLocation;
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ProximityAlert(int uid, double latitude, double longitude,
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float radius, long expiration, PendingIntent intent) {
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mUid = uid;
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLatitude = latitude;
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLongitude = longitude;
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRadius = radius;
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mExpiration = expiration;
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mIntent = intent;
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocation = new Location("");
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocation.setLatitude(latitude);
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocation.setLongitude(longitude);
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long getExpiration() {
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mExpiration;
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PendingIntent getIntent() {
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mIntent;
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10852d2078aa1d6e31063f565a20b717f3b8908fff02Yusuf T. Mobile        boolean isInProximity(double latitude, double longitude, float accuracy) {
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Location loc = new Location("");
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            loc.setLatitude(latitude);
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            loc.setLongitude(longitude);
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            double radius = loc.distanceTo(mLocation);
10912d2078aa1d6e31063f565a20b717f3b8908fff02Yusuf T. Mobile            return radius <= Math.max(mRadius,accuracy);
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "ProximityAlert{"
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Integer.toHexString(System.identityHashCode(this))
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " uid " + mUid + mIntent + "}";
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void dump(PrintWriter pw, String prefix) {
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + this);
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mLatitude=" + mLatitude + " mLongitude=" + mLongitude);
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mRadius=" + mRadius + " mExpiration=" + mExpiration);
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mIntent=" + mIntent);
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println(prefix + "mLocation:");
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLocation.dump(new PrintWriterPrinter(pw), prefix + "  ");
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Listener for receiving locations to trigger proximity alerts
111248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    class ProximityListener extends ILocationListener.Stub implements PendingIntent.OnFinished {
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean isGpsAvailable = false;
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Note: this is called with the lock held.
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onLocationChanged(Location loc) {
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If Gps is available, then ignore updates from NetworkLocationProvider
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (loc.getProvider().equals(LocationManager.GPS_PROVIDER)) {
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                isGpsAvailable = true;
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isGpsAvailable && loc.getProvider().equals(LocationManager.NETWORK_PROVIDER)) {
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Process proximity alerts
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long now = System.currentTimeMillis();
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            double latitude = loc.getLatitude();
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            double longitude = loc.getLongitude();
11312d2078aa1d6e31063f565a20b717f3b8908fff02Yusuf T. Mobile            float accuracy = loc.getAccuracy();
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<PendingIntent> intentsToRemove = null;
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (ProximityAlert alert : mProximityAlerts.values()) {
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PendingIntent intent = alert.getIntent();
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long expiration = alert.getExpiration();
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if ((expiration == -1) || (now <= expiration)) {
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    boolean entered = mProximitiesEntered.contains(alert);
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    boolean inProximity =
11412d2078aa1d6e31063f565a20b717f3b8908fff02Yusuf T. Mobile                        alert.isInProximity(latitude, longitude, accuracy);
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!entered && inProximity) {
1143105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        if (LOCAL_LOGV) {
1144105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                            Log.v(TAG, "Entered alert");
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mProximitiesEntered.add(alert);
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Intent enteredIntent = new Intent();
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        enteredIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, true);
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        try {
11500528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                            synchronized (this) {
11510528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                                // synchronize to ensure incrementPendingBroadcasts()
115248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // is called before decrementPendingBroadcasts()
115348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                intent.send(mContext, 0, enteredIntent, this, mLocationHandler);
115448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // call this after broadcasting so we do not increment
115548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // if we throw an exeption.
11560528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                                incrementPendingBroadcasts();
115748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            }
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } catch (PendingIntent.CanceledException e) {
1159105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                            if (LOCAL_LOGV) {
1160105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                                Log.v(TAG, "Canceled proximity alert: " + alert, e);
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (intentsToRemove == null) {
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                intentsToRemove = new ArrayList<PendingIntent>();
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            intentsToRemove.add(intent);
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else if (entered && !inProximity) {
1168105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        if (LOCAL_LOGV) {
1169105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                            Log.v(TAG, "Exited alert");
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mProximitiesEntered.remove(alert);
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Intent exitedIntent = new Intent();
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        exitedIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, false);
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        try {
11750528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                            synchronized (this) {
11760528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                                // synchronize to ensure incrementPendingBroadcasts()
117748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // is called before decrementPendingBroadcasts()
117848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                intent.send(mContext, 0, exitedIntent, this, mLocationHandler);
117948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // call this after broadcasting so we do not increment
118048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                                // if we throw an exeption.
11810528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                                incrementPendingBroadcasts();
118248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            }
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } catch (PendingIntent.CanceledException e) {
1184105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                            if (LOCAL_LOGV) {
1185105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                                Log.v(TAG, "Canceled proximity alert: " + alert, e);
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (intentsToRemove == null) {
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                intentsToRemove = new ArrayList<PendingIntent>();
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            intentsToRemove.add(intent);
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Mark alert for expiration
1195105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                    if (LOCAL_LOGV) {
1196105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                        Log.v(TAG, "Expiring proximity alert: " + alert);
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (intentsToRemove == null) {
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        intentsToRemove = new ArrayList<PendingIntent>();
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    intentsToRemove.add(alert.getIntent());
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Remove expired alerts
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (intentsToRemove != null) {
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (PendingIntent i : intentsToRemove) {
12080dac8c0f7ec00d94b09f92823fa238142163aba8Mike Lockwood                    ProximityAlert alert = mProximityAlerts.remove(i);
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mProximitiesEntered.remove(alert);
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Note: this is called with the lock held.
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onProviderDisabled(String provider) {
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (provider.equals(LocationManager.GPS_PROVIDER)) {
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                isGpsAvailable = false;
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Note: this is called with the lock held.
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onProviderEnabled(String provider) {
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ignore
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Note: this is called with the lock held.
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onStatusChanged(String provider, int status, Bundle extras) {
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((provider.equals(LocationManager.GPS_PROVIDER)) &&
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (status != LocationProvider.AVAILABLE)) {
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                isGpsAvailable = false;
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
123348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
123448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        public void onSendFinished(PendingIntent pendingIntent, Intent intent,
123548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                int resultCode, String resultData, Bundle resultExtras) {
12360528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            // synchronize to ensure incrementPendingBroadcasts()
12370528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            // is called before decrementPendingBroadcasts()
12380528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            synchronized (this) {
12390528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                decrementPendingBroadcasts();
12400528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
124148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addProximityAlert(double latitude, double longitude,
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float radius, long expiration, PendingIntent intent) {
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
12472f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                addProximityAlertLocked(latitude, longitude, radius, expiration, intent);
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "addProximityAlert got exception:", e);
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void addProximityAlertLocked(double latitude, double longitude,
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float radius, long expiration, PendingIntent intent) {
1259105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
1260105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "addProximityAlert: latitude = " + latitude +
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ", longitude = " + longitude +
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ", expiration = " + expiration +
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ", intent = " + intent);
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Require ability to access all providers for now
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isAllowedProviderSafe(LocationManager.GPS_PROVIDER) ||
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            !isAllowedProviderSafe(LocationManager.NETWORK_PROVIDER)) {
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_FINE_LOCATION permission");
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (expiration != -1) {
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            expiration += System.currentTimeMillis();
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ProximityAlert alert = new ProximityAlert(Binder.getCallingUid(),
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                latitude, longitude, radius, expiration, intent);
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProximityAlerts.put(intent, alert);
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
127948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        if (mProximityReceiver == null) {
128048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            mProximityListener = new ProximityListener();
128148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            mProximityReceiver = new Receiver(mProximityListener);
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
128395427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            for (int i = mProviders.size() - 1; i >= 0; i--) {
128495427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood                LocationProviderProxy provider = mProviders.get(i);
128548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver);
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeProximityAlert(PendingIntent intent) {
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
12922f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               removeProximityAlertLocked(intent);
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "removeProximityAlert got exception:", e);
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void removeProximityAlertLocked(PendingIntent intent) {
1303105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (LOCAL_LOGV) {
1304105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            Log.v(TAG, "removeProximityAlert: intent = " + intent);
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mProximityAlerts.remove(intent);
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mProximityAlerts.size() == 0) {
130948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            removeUpdatesLocked(mProximityReceiver);
131048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            mProximityReceiver = null;
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProximityListener = null;
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     }
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return null if the provider does not exits
1317f2db9fb0f877057a9ef56908d54f3c95fc3fd552Alexey Tarasov     * @throws SecurityException if the provider is not allowed to be
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * accessed by the caller
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Bundle getProviderInfo(String provider) {
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
13222f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _getProviderInfoLocked(provider);
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "_getProviderInfo got exception:", e);
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Bundle _getProviderInfoLocked(String provider) {
133415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        LocationProviderProxy p = mProvidersByName.get(provider);
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bundle b = new Bundle();
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("network", p.requiresNetwork());
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("satellite", p.requiresSatellite());
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("cell", p.requiresCell());
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("cost", p.hasMonetaryCost());
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("altitude", p.supportsAltitude());
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("speed", p.supportsSpeed());
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putBoolean("bearing", p.supportsBearing());
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putInt("power", p.getPowerRequirement());
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        b.putInt("accuracy", p.getAccuracy());
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return b;
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isProviderEnabled(String provider) {
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
13572f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _isProviderEnabledLocked(provider);
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "isProviderEnabled got exception:", e);
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1368275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood    public void reportLocation(Location location) {
1369275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
1370275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood                != PackageManager.PERMISSION_GRANTED) {
1371275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood            throw new SecurityException("Requires INSTALL_LOCATION_PROVIDER permission");
1372275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        }
1373275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood
13744e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location);
13754e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location);
13764e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        mLocationHandler.sendMessageAtFrontOfQueue(m);
13774e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    }
13784e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean _isProviderEnabledLocked(String provider) {
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
138215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        LocationProviderProxy p = mProvidersByName.get(provider);
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("provider=" + provider);
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return isAllowedBySettingsLocked(provider);
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Location getLastKnownLocation(String provider) {
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
13912f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return _getLastKnownLocationLocked(provider);
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (SecurityException se) {
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw se;
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(TAG, "getLastKnownLocation got exception:", e);
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Location _getLastKnownLocationLocked(String provider) {
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermissionsSafe(provider);
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
140515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        LocationProviderProxy p = mProvidersByName.get(provider);
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("provider=" + provider);
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isAllowedBySettingsLocked(provider)) {
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14149aa1fa2d3612d1d8ffeae6552d65669f4ca194d9Mike Lockwood        return mLastKnownLocation.get(provider);
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean shouldBroadcastSafe(Location loc, Location lastLoc, UpdateRecord record) {
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Always broadcast the first update
14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (lastLoc == null) {
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Don't broadcast same location again regardless of condition
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO - we should probably still rebroadcast if user explicitly sets a minTime > 0
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (loc.getTime() == lastLoc.getTime()) {
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Check whether sufficient distance has been traveled
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        double minDistance = record.mMinDistance;
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (minDistance > 0.0) {
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (loc.distanceTo(lastLoc) <= minDistance) {
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14404e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood    private void handleLocationChangedLocked(Location location) {
14414e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        String provider = location.getProvider();
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (records == null || records.size() == 0) {
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
144715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        LocationProviderProxy p = mProvidersByName.get(provider);
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14524e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        // Update last known location for provider
14534e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        Location lastLocation = mLastKnownLocation.get(provider);
14544e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        if (lastLocation == null) {
14554e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood            mLastKnownLocation.put(provider, new Location(location));
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14574e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood            lastLocation.set(location);
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Fetch latest status update time
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long newStatusUpdateTime = p.getStatusUpdateTime();
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14637ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood       // Get latest status
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bundle extras = new Bundle();
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int status = p.getStatus(extras);
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<Receiver> deadReceivers = null;
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Broadcast location or status to all listeners
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int N = records.size();
14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i=0; i<N; i++) {
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            UpdateRecord r = records.get(i);
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Receiver receiver = r.mReceiver;
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14752f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            Location lastLoc = r.mLastFixBroadcast;
14764e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood            if ((lastLoc == null) || shouldBroadcastSafe(location, lastLoc, r)) {
14774e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                if (lastLoc == null) {
14784e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    lastLoc = new Location(location);
14792f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    r.mLastFixBroadcast = lastLoc;
14804e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                } else {
14814e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    lastLoc.set(location);
14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14834e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                if (!receiver.callLocationChangedLocked(location)) {
14844e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    Log.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
14854e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    if (deadReceivers == null) {
14864e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                        deadReceivers = new ArrayList<Receiver>();
14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
14884e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    deadReceivers.add(receiver);
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14922f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            long prevStatusUpdateTime = r.mLastStatusBroadcast;
14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((newStatusUpdateTime > prevStatusUpdateTime) &&
14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14962f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                r.mLastStatusBroadcast = newStatusUpdateTime;
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!receiver.callStatusChangedLocked(provider, status, extras)) {
14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (deadReceivers == null) {
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        deadReceivers = new ArrayList<Receiver>();
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!deadReceivers.contains(receiver)) {
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        deadReceivers.add(receiver);
15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (deadReceivers != null) {
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=deadReceivers.size()-1; i>=0; i--) {
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeUpdatesLocked(deadReceivers.get(i));
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class LocationWorkerHandler extends Handler {
15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void handleMessage(Message msg) {
15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
15214e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                if (msg.what == MESSAGE_LOCATION_CHANGED) {
15224e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                    // log("LocationWorkerHandler: MESSAGE_LOCATION_CHANGED!");
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15242f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                    synchronized (mLock) {
15254e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                        Location location = (Location) msg.obj;
1526fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                        String provider = location.getProvider();
152798cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood
1528fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                        // notify other providers of the new location
1529fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                        for (int i = mProviders.size() - 1; i >= 0; i--) {
1530fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                            LocationProviderProxy proxy = mProviders.get(i);
1531fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                            if (!provider.equals(proxy.getName())) {
1532fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                                proxy.updateLocation(location);
153398cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood                            }
153498cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood                        }
153598cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood
1536fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                        if (isAllowedBySettingsLocked(provider)) {
1537fd6e5f0dda50e113db4ccc55338b6c4f09da37a4Mike Lockwood                            handleLocationChangedLocked(location);
15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (Exception e) {
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Log, don't crash!
15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.e(TAG, "Exception in LocationWorkerHandler.handleMessage:", e);
15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15480528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
15490528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        @Override
15500528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        public void onReceive(Context context, Intent intent) {
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String action = intent.getAction();
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15530528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
155408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    || action.equals(Intent.ACTION_PACKAGE_RESTARTED)
155508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    || action.equals(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE)) {
15562f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                synchronized (mLock) {
155708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    int uidList[] = null;
155808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    if (action.equals(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE)) {
155908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        uidList = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
156008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    } else {
156108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        uidList = new int[]{intent.getIntExtra(Intent.EXTRA_UID, -1)};
156208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    }
156308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    if (uidList == null || uidList.length == 0) {
156408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        return;
156508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    }
156608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    for (int uid : uidList) {
156708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        if (uid >= 0) {
156808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            ArrayList<Receiver> removedRecs = null;
156908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            for (ArrayList<UpdateRecord> i : mRecordsByProvider.values()) {
157008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                for (int j=i.size()-1; j>=0; j--) {
157108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    UpdateRecord ur = i.get(j);
157208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    if (ur.mReceiver.isPendingIntent() && ur.mUid == uid) {
157308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                        if (removedRecs == null) {
157408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                            removedRecs = new ArrayList<Receiver>();
157508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                        }
157608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                        if (!removedRecs.contains(ur.mReceiver)) {
157708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                            removedRecs.add(ur.mReceiver);
157808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                        }
15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    }
15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
158208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            ArrayList<ProximityAlert> removedAlerts = null;
158308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            for (ProximityAlert i : mProximityAlerts.values()) {
158408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                if (i.mUid == uid) {
158508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    if (removedAlerts == null) {
158608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                        removedAlerts = new ArrayList<ProximityAlert>();
158708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    }
158808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    if (!removedAlerts.contains(i)) {
158908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                        removedAlerts.add(i);
159008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    }
15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                }
15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
159308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            if (removedRecs != null) {
159408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                for (int i=removedRecs.size()-1; i>=0; i--) {
159508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    removeUpdatesLocked(removedRecs.get(i));
159608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                }
15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
159808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            if (removedAlerts != null) {
159908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                for (int i=removedAlerts.size()-1; i>=0; i--) {
160008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                    removeProximityAlertLocked(removedAlerts.get(i).mIntent);
160108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                }
16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16060528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean noConnectivity =
16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
16099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!noConnectivity) {
16104df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    mNetworkState = LocationProvider.AVAILABLE;
16114df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                } else {
16124df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
161403d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                NetworkInfo info =
161508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    (NetworkInfo)intent.getExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Notify location providers of current network state
16182f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                synchronized (mLock) {
161915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                    for (int i = mProviders.size() - 1; i >= 0; i--) {
162015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                        LocationProviderProxy provider = mProviders.get(i);
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (provider.requiresNetwork()) {
162203d246779ea65fc2bd10d0b4f32620f45211133aMike Lockwood                            provider.updateNetworkState(mNetworkState, info);
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16280528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    };
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Wake locks
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16320528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private void incrementPendingBroadcasts() {
16330528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        synchronized (mWakeLock) {
16340528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (mPendingBroadcasts++ == 0) {
16350528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                try {
16360528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    mWakeLock.acquire();
16370528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    log("Acquired wakelock");
16380528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                } catch (Exception e) {
16390528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // This is to catch a runtime exception thrown when we try to release an
16400528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // already released lock.
16410528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    Log.e(TAG, "exception in acquireWakeLock()", e);
16420528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                }
16430528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
164448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
164548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
164648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
164748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private void decrementPendingBroadcasts() {
16480528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        synchronized (mWakeLock) {
164948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (--mPendingBroadcasts == 0) {
16500528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                try {
16510528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // Release wake lock
16520528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    if (mWakeLock.isHeld()) {
16530528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                        mWakeLock.release();
16540528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                        log("Released wakelock");
16550528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    } else {
16560528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                        log("Can't release wakelock again!");
16570528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    }
16580528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                } catch (Exception e) {
16590528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // This is to catch a runtime exception thrown when we try to release an
16600528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // already released lock.
16610528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    Log.e(TAG, "exception in releaseWakeLock()", e);
16620528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                }
166348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
166448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
166548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
166648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Geocoder
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String getFromLocation(double latitude, double longitude, int maxResults,
167034901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwood            GeocoderParams params, List<Address> addrs) {
1671a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        if (mGeocodeProvider != null) {
1672a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            try {
167334901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwood                return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
167434901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwood                        params, addrs);
1675a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            } catch (RemoteException e) {
1676a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood                Log.e(TAG, "getFromLocation failed", e);
16773681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood                mGeocodeProvider = null;
16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1680a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        return null;
16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1683a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood
16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String getFromLocationName(String locationName,
1685a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            double lowerLeftLatitude, double lowerLeftLongitude,
1686a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            double upperRightLatitude, double upperRightLongitude, int maxResults,
168734901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwood            GeocoderParams params, List<Address> addrs) {
1688a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood
1689a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        if (mGeocodeProvider != null) {
1690a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            try {
1691a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood                return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
1692a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood                        lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
169334901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwood                        maxResults, params, addrs);
1694a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            } catch (RemoteException e) {
1695a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood                Log.e(TAG, "getFromLocationName failed", e);
16963681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood                mGeocodeProvider = null;
16979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1699a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        return null;
17009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Mock Providers
17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void checkMockPermissionsSafe() {
17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(),
17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1;
17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!allowMocks) {
17089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting");
17099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) !=
17129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PackageManager.PERMISSION_GRANTED) {
17139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission");
17149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite,
17189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
17199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
17209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
172286328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood        long identity = Binder.clearCallingIdentity();
17232f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
17244e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood            MockProvider provider = new MockProvider(name, this,
17254e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood                requiresNetwork, requiresSatellite,
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                requiresCell, hasMonetaryCost, supportsAltitude,
17279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                supportsSpeed, supportsBearing, powerRequirement, accuracy);
17287566c1debebe072af76411e11d96810fd1409482Mike Lockwood            // remove the real provider if we are replacing GPS or network provider
17297566c1debebe072af76411e11d96810fd1409482Mike Lockwood            if (LocationManager.GPS_PROVIDER.equals(name)
17307566c1debebe072af76411e11d96810fd1409482Mike Lockwood                    || LocationManager.NETWORK_PROVIDER.equals(name)) {
17317566c1debebe072af76411e11d96810fd1409482Mike Lockwood                LocationProviderProxy proxy = mProvidersByName.get(name);
17327566c1debebe072af76411e11d96810fd1409482Mike Lockwood                if (proxy != null) {
17337566c1debebe072af76411e11d96810fd1409482Mike Lockwood                    proxy.enableLocationTracking(false);
17347566c1debebe072af76411e11d96810fd1409482Mike Lockwood                    removeProvider(proxy);
17357566c1debebe072af76411e11d96810fd1409482Mike Lockwood                }
17367566c1debebe072af76411e11d96810fd1409482Mike Lockwood            }
173715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (mProvidersByName.get(name) != null) {
17389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
17399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
174015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            addProvider(new LocationProviderProxy(name, provider));
17417ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mMockProviders.put(name, provider);
17427566c1debebe072af76411e11d96810fd1409482Mike Lockwood            mLastKnownLocation.put(name, null);
17439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
17449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
174586328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood        Binder.restoreCallingIdentity(identity);
17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeTestProvider(String provider) {
17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17502f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
17517ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
17527ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
175586328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            long identity = Binder.clearCallingIdentity();
175615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            removeProvider(mProvidersByName.get(provider));
17577ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mMockProviders.remove(mockProvider);
17587566c1debebe072af76411e11d96810fd1409482Mike Lockwood            // reinstall real provider if we were mocking GPS or network provider
17597566c1debebe072af76411e11d96810fd1409482Mike Lockwood            if (LocationManager.GPS_PROVIDER.equals(provider) &&
17607566c1debebe072af76411e11d96810fd1409482Mike Lockwood                    mGpsLocationProvider != null) {
17617566c1debebe072af76411e11d96810fd1409482Mike Lockwood                addProvider(mGpsLocationProvider);
17627566c1debebe072af76411e11d96810fd1409482Mike Lockwood            } else if (LocationManager.NETWORK_PROVIDER.equals(provider) &&
17637566c1debebe072af76411e11d96810fd1409482Mike Lockwood                    mNetworkLocationProvider != null) {
17647566c1debebe072af76411e11d96810fd1409482Mike Lockwood                addProvider(mNetworkLocationProvider);
17657566c1debebe072af76411e11d96810fd1409482Mike Lockwood            }
17667566c1debebe072af76411e11d96810fd1409482Mike Lockwood            mLastKnownLocation.put(provider, null);
17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
176886328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            Binder.restoreCallingIdentity(identity);
17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderLocation(String provider, Location loc) {
17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17742f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
17757ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
17767ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
177995427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
178095427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            long identity = Binder.clearCallingIdentity();
17817ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.setLocation(loc);
178295427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            Binder.restoreCallingIdentity(identity);
17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderLocation(String provider) {
17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17882f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
17897ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
17907ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
17929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17937ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.clearLocation();
17949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderEnabled(String provider, boolean enabled) {
17989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17992f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18007ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18017ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
180486328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            long identity = Binder.clearCallingIdentity();
18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (enabled) {
18067ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                mockProvider.enable();
18079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEnabledProviders.add(provider);
18089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDisabledProviders.remove(provider);
18099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
18107ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                mockProvider.disable();
18119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEnabledProviders.remove(provider);
18129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDisabledProviders.add(provider);
18139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
181586328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            Binder.restoreCallingIdentity(identity);
18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderEnabled(String provider) {
18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18212f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18227ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18237ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
182686328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            long identity = Binder.clearCallingIdentity();
18279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEnabledProviders.remove(provider);
18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDisabledProviders.remove(provider);
18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
183086328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            Binder.restoreCallingIdentity(identity);
18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
18359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18362f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18377ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18387ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18417ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.setStatus(status, extras, updateTime);
18429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderStatus(String provider) {
18469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18472f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18487ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18497ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18527ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.clearStatus();
18539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void log(String log) {
18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Log.isLoggable(TAG, Log.VERBOSE)) {
18589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.d(TAG, log);
18599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
18650528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            pw.println("Permission Denial: can't dump LocationManagerService from from pid="
18669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Binder.getCallingPid()
18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", uid=" + Binder.getCallingUid());
18689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
18699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18712f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("Current Location Manager state:");
18739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  sProvidersLoaded=" + sProvidersLoaded);
18749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Listeners:");
18752f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            int N = mReceivers.size();
18769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
18772f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                pw.println("    " + mReceivers.get(i));
18789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Location Listeners:");
18802f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            for (Receiver i : mReceivers.values()) {
18812f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                pw.println("    " + i + ":");
18822f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                for (Map.Entry<String,UpdateRecord> j : i.mUpdateRecords.entrySet()) {
18839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("      " + j.getKey() + ":");
18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    j.getValue().dump(pw, "        ");
18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Records by Provider:");
18889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (Map.Entry<String, ArrayList<UpdateRecord>> i
18899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    : mRecordsByProvider.entrySet()) {
18909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("    " + i.getKey() + ":");
18919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (UpdateRecord j : i.getValue()) {
18929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("      " + j + ":");
18939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    j.dump(pw, "        ");
18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Last Known Locations:");
18979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (Map.Entry<String, Location> i
18989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    : mLastKnownLocation.entrySet()) {
18999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("    " + i.getKey() + ":");
19009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                i.getValue().dump(new PrintWriterPrinter(pw), "      ");
19019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mProximityAlerts.size() > 0) {
19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Proximity Alerts:");
19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (Map.Entry<PendingIntent, ProximityAlert> i
19059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        : mProximityAlerts.entrySet()) {
19069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i.getKey() + ":");
19079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    i.getValue().dump(pw, "      ");
19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mProximitiesEntered.size() > 0) {
19119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Proximities Entered:");
19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (ProximityAlert i : mProximitiesEntered) {
19139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i + ":");
19149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    i.dump(pw, "      ");
19159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
191748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            pw.println("  mProximityReceiver=" + mProximityReceiver);
19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  mProximityListener=" + mProximityListener);
19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mEnabledProviders.size() > 0) {
19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Enabled Providers:");
19219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (String i : mEnabledProviders) {
19229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i);
19239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mDisabledProviders.size() > 0) {
19279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Disabled Providers:");
19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (String i : mDisabledProviders) {
19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i);
19309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mMockProviders.size() > 0) {
19349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Mock Providers:");
19359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
19367ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                    i.getValue().dump(pw, "      ");
19379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1942