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 android.app.PendingIntent;
2038389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Leaseimport android.content.BroadcastReceiver;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
2438389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Leaseimport android.content.IntentFilter;
256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.content.pm.ApplicationInfo;
26fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamiltonimport android.content.pm.PackageInfo;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
286fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.content.pm.PackageManager.NameNotFoundException;
29fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamiltonimport android.content.pm.ResolveInfo;
30fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamiltonimport android.content.pm.Signature;
31628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwoodimport android.content.res.Resources;
32bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsuimport android.database.ContentObserver;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Address;
3403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwoodimport android.location.Criteria;
3534901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwoodimport android.location.GeocoderParams;
366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.location.Geofence;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.IGpsStatusListener;
3815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwoodimport android.location.IGpsStatusProvider;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.ILocationListener;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.ILocationManager;
4122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport android.location.INetInitiatedListener;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Location;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationManager;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationProvider;
456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.location.LocationRequest;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
503d12b51ee38537f6760a833618948f936e75561dMike Lockwoodimport android.os.Looper;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager;
53e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwoodimport android.os.Process;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.os.SystemClock;
565ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackbornimport android.os.UserHandle;
577e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackbornimport android.os.WorkSource;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
608a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
62e97ae40dffe7d7f8917c51c4f3f6c1b18c238565Mike Lockwoodimport com.android.internal.content.PackageMonitor;
636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport com.android.internal.location.ProviderProperties;
646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport com.android.internal.location.ProviderRequest;
6543e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport com.android.server.location.GeocoderProxy;
66e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pellyimport com.android.server.location.GeofenceManager;
6743e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport com.android.server.location.GpsLocationProvider;
684035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pellyimport com.android.server.location.LocationBlacklist;
6974fa7eabda3d0c1a85e0b568e3fc4230ed4fe7a4Nick Pellyimport com.android.server.location.LocationFudger;
7043e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport com.android.server.location.LocationProviderInterface;
7143e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport com.android.server.location.LocationProviderProxy;
7243e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport com.android.server.location.MockProvider;
7343e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport com.android.server.location.PassiveProvider;
7443e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwood
7543e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.io.FileDescriptor;
7643e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.io.PrintWriter;
7743e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.util.ArrayList;
786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport java.util.Arrays;
7943e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.util.HashMap;
8043e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.util.HashSet;
8143e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.util.List;
8243e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.util.Map;
8343e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.util.Set;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The service class that manages LocationProviders and issues location
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * updates and alerts.
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
89bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsupublic class LocationManagerService extends ILocationManager.Stub implements Runnable {
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "LocationManagerService";
916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public static final boolean D = false;
926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final String WAKELOCK_KEY = TAG;
946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final String THREAD_NAME = TAG;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    // Location resolution level: no location data whatsoever
9737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private static final int RESOLUTION_LEVEL_NONE = 0;
9837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    // Location resolution level: coarse location data only
9937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private static final int RESOLUTION_LEVEL_COARSE = 1;
10037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    // Location resolution level: fine location data
10137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private static final int RESOLUTION_LEVEL_FINE = 2;
10237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_MOCK_LOCATION =
1046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            android.Manifest.permission.ACCESS_MOCK_LOCATION;
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
1066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
107275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood    private static final String INSTALL_LOCATION_PROVIDER =
1086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
1096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final String NETWORK_LOCATION_SERVICE_ACTION =
1116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            "com.android.location.service.v2.NetworkLocationProvider";
1126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final String FUSED_LOCATION_SERVICE_ACTION =
1136fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            "com.android.location.service.FusedLocationProvider";
1146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1156fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final int MSG_LOCATION_CHANGED = 1;
1166fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
117f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly    // Location Providers may sometimes deliver location updates
118f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly    // slightly faster that requested - provide grace period so
119f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly    // we don't unnecessarily filter events that are otherwise on
120f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly    // time
1216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
122f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly
1236fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final Context mContext;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // used internally for synchronization
1286fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final Object mLock = new Object();
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // --- fields below are final after init() ---
13174fa7eabda3d0c1a85e0b568e3fc4230ed4fe7a4Nick Pelly    private LocationFudger mLocationFudger;
1326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private GeofenceManager mGeofenceManager;
1336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private PowerManager.WakeLock mWakeLock;
1346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private PackageManager mPackageManager;
135628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood    private GeocoderProxy mGeocodeProvider;
13615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private IGpsStatusProvider mGpsStatusProvider;
13722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private INetInitiatedListener mNetInitiatedListener;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private LocationWorkerHandler mLocationHandler;
1394035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    private PassiveProvider mPassiveProvider;  // track passive provider for special cases
1404035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    private LocationBlacklist mBlacklist;
1416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // --- fields below are protected by mWakeLock ---
1436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private int mPendingBroadcasts;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // --- fields below are protected by mLock ---
1466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // Set of providers that are explicitly enabled
1476fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final Set<String> mEnabledProviders = new HashSet<String>();
1487566c1debebe072af76411e11d96810fd1409482Mike Lockwood
1496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // Set of providers that are explicitly disabled
1506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final Set<String> mDisabledProviders = new HashSet<String>();
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // Mock (test) providers
1536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final HashMap<String, MockProvider> mMockProviders =
1546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            new HashMap<String, MockProvider>();
155e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
1566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // all receivers
1572f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final HashMap<Object, Receiver> mReceivers = new HashMap<Object, Receiver>();
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // currently installed providers (with mocks replacing real providers)
160d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    private final ArrayList<LocationProviderInterface> mProviders =
1616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            new ArrayList<LocationProviderInterface>();
16215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
1636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // real providers, saved here when mocked out
1646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final HashMap<String, LocationProviderInterface> mRealProviders =
1656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            new HashMap<String, LocationProviderInterface>();
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // mapping from provider name to provider
1686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final HashMap<String, LocationProviderInterface> mProvidersByName =
1696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            new HashMap<String, LocationProviderInterface>();
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // mapping from provider name to all its UpdateRecords
1726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
1736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            new HashMap<String, ArrayList<UpdateRecord>>();
1746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // mapping from provider name to last known location
1766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final HashMap<String, Location> mLastLocation = new HashMap<String, Location>();
1777e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn
1786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // all providers that operate over proxy, for authorizing incoming location
1796fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final ArrayList<LocationProviderProxy> mProxyProviders =
1806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            new ArrayList<LocationProviderProxy>();
1816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
18238389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease    // current active user on the device - other users are denied location data
18338389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease    private int mCurrentUserId = UserHandle.USER_OWNER;
18438389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease
1856fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public LocationManagerService(Context context) {
1866fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        super();
1876fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mContext = context;
1886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "Constructed");
1906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // most startup is deferred until systemReady()
1926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
1936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void systemReady() {
1956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Thread thread = new Thread(null, this, THREAD_NAME);
1966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        thread.start();
1976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
1986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
2006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void run() {
2016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
2026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Looper.prepare();
2036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mLocationHandler = new LocationWorkerHandler();
2046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        init();
2056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Looper.loop();
2066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
2076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void init() {
2096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "init()");
2106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
2126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
2136fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mPackageManager = mContext.getPackageManager();
2146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
215bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu        mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
216bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu        mBlacklist.init();
217df9ec6171f6b7f3075d7f8174e9ae6ecf080c917Victoria Lease        mLocationFudger = new LocationFudger(mContext, mLocationHandler);
218bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu
2196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        synchronized (mLock) {
2206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            loadProvidersLocked();
2216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
222bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu
2234035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
2246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // listen for settings changes
226bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu        mContext.getContentResolver().registerContentObserver(
22775defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu                Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
228bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu                new ContentObserver(mLocationHandler) {
229bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu           @Override
230bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu            public void onChange(boolean selfChange) {
231bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu               synchronized (mLock) {
232bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu                   updateProvidersLocked();
233bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu               }
234bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu            }
235b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        }, UserHandle.USER_ALL);
2366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mPackageMonitor.register(mContext, Looper.myLooper(), true);
237bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu
23838389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        // listen for user change
23938389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        IntentFilter intentFilter = new IntentFilter();
24038389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
24138389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease
24238389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        mContext.registerReceiverAsUser(new BroadcastReceiver() {
24338389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease            @Override
24438389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease            public void onReceive(Context context, Intent intent) {
24538389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease                String action = intent.getAction();
24638389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease                if (Intent.ACTION_USER_SWITCHED.equals(action)) {
24738389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease                    switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
24838389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease                }
24938389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease            }
25038389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        }, UserHandle.ALL, intentFilter, null, null);
25138389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease
252bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu        updateProvidersLocked();
2536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
2546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
255fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton    private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) {
256fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        PackageManager pm = mContext.getPackageManager();
257fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        String systemPackageName = mContext.getPackageName();
258fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
259fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
260fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
261fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                new Intent(FUSED_LOCATION_SERVICE_ACTION),
262fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                PackageManager.GET_META_DATA, mCurrentUserId);
263fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        for (ResolveInfo rInfo : rInfos) {
264fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            String packageName = rInfo.serviceInfo.packageName;
265fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
266fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            // Check that the signature is in the list of supported sigs. If it's not in
267fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            // this list the standard provider binding logic won't bind to it.
268fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            try {
269fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                PackageInfo pInfo;
270fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
271fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
272fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                    Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
273fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                            ", but has wrong signature, ignoring");
274fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                    continue;
275fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                }
276fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            } catch (NameNotFoundException e) {
277fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                Log.e(TAG, "missing package: " + packageName);
278fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                continue;
279fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            }
280fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
281fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            // Get the version info
282fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            if (rInfo.serviceInfo.metaData == null) {
283fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                Log.w(TAG, "Found fused provider without metadata: " + packageName);
284fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                continue;
285fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            }
286fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
287fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            int version = rInfo.serviceInfo.metaData.getInt(
288fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                    ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
289fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            if (version == 0) {
290fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                // This should be the fallback fused location provider.
291fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
292fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                // Make sure it's in the system partition.
293fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
294fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                    if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
295fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                    continue;
296fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                }
297fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
298fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                // Check that the fallback is signed the same as the OS
299fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                // as a proxy for coreApp="true"
300fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                if (pm.checkSignatures(systemPackageName, packageName)
301fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                        != PackageManager.SIGNATURE_MATCH) {
302fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                    if (D) Log.d(TAG, "Fallback candidate not signed the same as system: "
303fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                            + packageName);
304fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                    continue;
305fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                }
306fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
307fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                // Found a valid fallback.
308fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                if (D) Log.d(TAG, "Found fallback provider: " + packageName);
309fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                return;
310fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            } else {
311fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
312fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            }
313fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        }
314fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
315fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        throw new IllegalStateException("Unable to find a fused location provider that is in the "
316fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                + "system partition with version 0 and signed with the platform certificate. "
317fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                + "Such a package is needed to provide a default fused location provider in the "
318fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                + "event that no other fused location provider has been installed or is currently "
319fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                + "available. For example, coreOnly boot mode when decrypting the data "
320fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
321fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton    }
322fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
3236fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void loadProvidersLocked() {
3245c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        // create a passive location provider, which is always enabled
3255c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        PassiveProvider passiveProvider = new PassiveProvider(this);
3265c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        addProviderLocked(passiveProvider);
3275c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        mEnabledProviders.add(passiveProvider.getName());
3285c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        mPassiveProvider = passiveProvider;
3295c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease
3306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (GpsLocationProvider.isSupported()) {
3316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // Create a gps location provider
3326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);
3336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
3346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
3356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            addProviderLocked(gpsProvider);
3366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mRealProviders.put(LocationManager.GPS_PROVIDER, gpsProvider);
3376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        /*
3406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Load package name(s) containing location provider support.
3416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        These packages can contain services implementing location providers:
3426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Geocoder Provider, Network Location Provider, and
3436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Fused Location Provider. They will each be searched for
3446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        service components implementing these providers.
3456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        The location framework also has support for installation
3466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        of new location providers at run-time. The new package does not
3476fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        have to be explicitly listed here, however it must have a signature
3486fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        that matches the signature of at least one package on this list.
3496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        */
3506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Resources resources = mContext.getResources();
3516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        ArrayList<String> providerPackageNames = new ArrayList<String>();
352fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        String[] pkgs = resources.getStringArray(
3536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                com.android.internal.R.array.config_locationProviderPackageNames);
354fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        if (D) Log.d(TAG, "certificates for location providers pulled from: " +
355fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                Arrays.toString(pkgs));
356fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));
357fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
358fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        ensureFallbackFusedProviderPresentLocked(providerPackageNames);
3596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
3606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // bind to network provider
3616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
3626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                mContext,
3636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                LocationManager.NETWORK_PROVIDER,
3646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                NETWORK_LOCATION_SERVICE_ACTION,
365b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                providerPackageNames, mLocationHandler, mCurrentUserId);
3666fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (networkProvider != null) {
3676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
3686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mProxyProviders.add(networkProvider);
3696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            addProviderLocked(networkProvider);
3706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else {
3716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            Slog.w(TAG,  "no network location provider found");
3726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
3736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
3746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // bind to fused provider
3756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(
3766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                mContext,
3776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                LocationManager.FUSED_PROVIDER,
3786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                FUSED_LOCATION_SERVICE_ACTION,
379b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                providerPackageNames, mLocationHandler, mCurrentUserId);
3806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (fusedLocationProvider != null) {
3816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            addProviderLocked(fusedLocationProvider);
3826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mProxyProviders.add(fusedLocationProvider);
3836fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mEnabledProviders.add(fusedLocationProvider.getName());
384c3575188c2f2ad27b1f03b9b9c0705a686a5e42fKenny Root            mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
3856fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else {
3866fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            Slog.e(TAG, "no fused location provider found",
3876fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    new IllegalStateException("Location service needs a fused location provider"));
3886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // bind to geocoder provider
391b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        mGeocodeProvider = GeocoderProxy.createAndBind(mContext, providerPackageNames,
392b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                mCurrentUserId);
3936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (mGeocodeProvider == null) {
3946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            Slog.e(TAG,  "no geocoder provider found");
3956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
3966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
3979637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
39938389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease     * Called when the device's active user changes.
40038389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease     * @param userId the new active user's UserId
40138389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease     */
40238389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease    private void switchUser(int userId) {
40383762d22c9bde92d412cf5a263a228d705606721Victoria Lease        mBlacklist.switchUser(userId);
40438389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        synchronized (mLock) {
405b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            mLastLocation.clear();
406b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            for (LocationProviderInterface p : mProviders) {
407b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                updateProviderListenersLocked(p.getName(), false, mCurrentUserId);
408269518e83efc01b387235d6194dcf93726e384ffVictoria Lease                p.switchUser(userId);
409b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            }
41038389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease            mCurrentUserId = userId;
411b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            updateProvidersLocked();
41238389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        }
41338389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease    }
41438389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease
41538389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease    /**
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A wrapper class holding either an ILocationListener or a PendingIntent to receive
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * location updates.
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
41948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
4206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final int mUid;  // uid of receiver
4216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final int mPid;  // pid of receiver
4226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final String mPackageName;  // package name of receiver
42337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        final int mAllowedResolutionLevel;  // resolution level allowed to receiver
4246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ILocationListener mListener;
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final PendingIntent mPendingIntent;
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Object mKey;
4286fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
4292f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
430f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly
43148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        int mPendingBroadcasts;
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
4346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                String packageName) {
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = listener;
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPendingIntent = intent;
4376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (listener != null) {
4386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                mKey = listener.asBinder();
4396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            } else {
4406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                mKey = intent;
4416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
44237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
4436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mUid = uid;
4446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mPid = pid;
4456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mPackageName = packageName;
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean equals(Object otherObj) {
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (otherObj instanceof Receiver) {
4516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                return mKey.equals(((Receiver)otherObj).mKey);
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int hashCode() {
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mKey.hashCode();
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4603681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
4636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            StringBuilder s = new StringBuilder();
4646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append("Reciever[");
4656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append(Integer.toHexString(System.identityHashCode(this)));
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
4676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                s.append(" listener");
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                s.append(" intent");
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (String p : mUpdateRecords.keySet()) {
4726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                s.append(" ").append(mUpdateRecords.get(p).toString());
4736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
4746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append("]");
4756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return s.toString();
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean isListener() {
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mListener != null;
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean isPendingIntent() {
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mPendingIntent != null;
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ILocationListener getListener() {
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mListener;
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("Request for non-existent listener");
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
49648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
49748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
49848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
49948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mListener.onStatusChanged(provider, status, extras);
500e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        // call this after broadcasting so we do not increment
501e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        // if we throw an exeption.
502e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        incrementPendingBroadcastsLocked();
50348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent statusChanged = new Intent();
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                statusChanged.putExtras(extras);
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
51248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
51348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
51448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
5156c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn                        mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
51637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                                getResolutionPermission(mAllowedResolutionLevel));
51748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
51848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
51948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
52048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (PendingIntent.CanceledException e) {
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean callLocationChangedLocked(Location location) {
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
53148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
53248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
53348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
53448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mListener.onLocationChanged(location);
535e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        // call this after broadcasting so we do not increment
536e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        // if we throw an exeption.
537e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        incrementPendingBroadcastsLocked();
53848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent locationChanged = new Intent();
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, location);
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
54648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
54748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
54848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
5496c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn                        mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
55037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                                getResolutionPermission(mAllowedResolutionLevel));
55148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
55248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
55348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
55448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
55548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                } catch (PendingIntent.CanceledException e) {
55648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    return false;
55748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
55848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
55948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            return true;
56048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
56148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
56248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        public boolean callProviderEnabledLocked(String provider, boolean enabled) {
56348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (mListener != null) {
56448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                try {
56548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
56648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
56748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
56848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (enabled) {
56948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            mListener.onProviderEnabled(provider);
57048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        } else {
57148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            mListener.onProviderDisabled(provider);
57248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
573e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        // call this after broadcasting so we do not increment
574e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        // if we throw an exeption.
575e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        incrementPendingBroadcastsLocked();
57648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
57748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                } catch (RemoteException e) {
57848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    return false;
57948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
58048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            } else {
58148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                Intent providerIntent = new Intent();
58248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
58348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                try {
58448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
58548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
58648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
5876c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn                        mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
58837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                                getResolutionPermission(mAllowedResolutionLevel));
58948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
59048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
59148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
59248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (PendingIntent.CanceledException e) {
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
600f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly        @Override
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
6026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (D) Log.d(TAG, "Location listener died");
6036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
6042f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeUpdatesLocked(this);
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
60748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            synchronized (this) {
60848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                if (mPendingBroadcasts > 0) {
60948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    LocationManagerService.this.decrementPendingBroadcasts();
61048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    mPendingBroadcasts = 0;
61148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
61248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
61348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
61448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
615e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        @Override
61648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        public void onSendFinished(PendingIntent pendingIntent, Intent intent,
61748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                int resultCode, String resultData, Bundle resultExtras) {
6180528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            synchronized (this) {
6190528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                decrementPendingBroadcastsLocked();
6200528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
62148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
62248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
6230528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // this must be called while synchronized by caller in a synchronized block
62448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        // containing the sending of the broadcaset
62548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        private void incrementPendingBroadcastsLocked() {
62648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (mPendingBroadcasts++ == 0) {
6270528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                LocationManagerService.this.incrementPendingBroadcasts();
62848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
62948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
63048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
6310528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        private void decrementPendingBroadcastsLocked() {
6320528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (--mPendingBroadcasts == 0) {
6330528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                LocationManagerService.this.decrementPendingBroadcasts();
63448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
63548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
63648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
63748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
638e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
63948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    public void locationCallbackFinished(ILocationListener listener) {
640080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //Do not use getReceiver here as that will add the ILocationListener to
641080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //the receiver list if it is not found.  If it is not found then the
642080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //LocationListener was removed when it had a pending broadcast and should
643080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //not be added back.
644080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        IBinder binder = listener.asBinder();
645080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        Receiver receiver = mReceivers.get(binder);
64648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        if (receiver != null) {
6470528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            synchronized (receiver) {
6480528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                // so wakelock calls will succeed
6490528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                long identity = Binder.clearCallingIdentity();
6500528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                receiver.decrementPendingBroadcastsLocked();
6510528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                Binder.restoreCallingIdentity(identity);
6520528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood           }
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void addProviderLocked(LocationProviderInterface provider) {
65715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProviders.add(provider);
65815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProvidersByName.put(provider.getName(), provider);
65915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
66015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
6616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void removeProviderLocked(LocationProviderInterface provider) {
6626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        provider.disable();
66315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProviders.remove(provider);
66415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProvidersByName.remove(provider.getName());
66515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
66615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
6673d12b51ee38537f6760a833618948f936e75561dMike Lockwood
668269518e83efc01b387235d6194dcf93726e384ffVictoria Lease    private boolean isAllowedBySettingsLocked(String provider, int userId) {
669269518e83efc01b387235d6194dcf93726e384ffVictoria Lease        if (userId != mCurrentUserId) {
670b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            return false;
671b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        }
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabledProviders.contains(provider)) {
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDisabledProviders.contains(provider)) {
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Use system settings
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ContentResolver resolver = mContext.getContentResolver();
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
681b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId);
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6846fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    /**
68537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Returns the permission string associated with the specified resolution level.
68637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
68737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param resolutionLevel the resolution level
68837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @return the permission string
6896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     */
69037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private String getResolutionPermission(int resolutionLevel) {
69137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        switch (resolutionLevel) {
69237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            case RESOLUTION_LEVEL_FINE:
69337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                return android.Manifest.permission.ACCESS_FINE_LOCATION;
69437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            case RESOLUTION_LEVEL_COARSE:
69537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                return android.Manifest.permission.ACCESS_COARSE_LOCATION;
69637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            default:
69737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                return null;
6986c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn        }
699da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease    }
7006c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn
701da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease    /**
70237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Returns the resolution level allowed to the given PID/UID pair.
70337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
70437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param pid the PID
70537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param uid the UID
70637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @return resolution level allowed to the pid/uid pair
707da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease     */
70837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private int getAllowedResolutionLevel(int pid, int uid) {
70937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
71037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                pid, uid) == PackageManager.PERMISSION_GRANTED) {
71137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            return RESOLUTION_LEVEL_FINE;
71237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
71337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                pid, uid) == PackageManager.PERMISSION_GRANTED) {
71437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            return RESOLUTION_LEVEL_COARSE;
71537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        } else {
71637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            return RESOLUTION_LEVEL_NONE;
717da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease        }
7184fab68b5324e1f9b6765cdc33e66d1f074623dc2Victoria Lease    }
7194fab68b5324e1f9b6765cdc33e66d1f074623dc2Victoria Lease
7204fab68b5324e1f9b6765cdc33e66d1f074623dc2Victoria Lease    /**
72137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Returns the resolution level allowed to the caller
72237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
72337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @return resolution level allowed to caller
72437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     */
72537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private int getCallerAllowedResolutionLevel() {
72637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
72737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    }
72837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease
72937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    /**
73037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Throw SecurityException if specified resolution level is insufficient to use geofences.
73137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
73237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param allowedResolutionLevel resolution level allowed to caller
7334fab68b5324e1f9b6765cdc33e66d1f074623dc2Victoria Lease     */
73437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
73537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
7364fab68b5324e1f9b6765cdc33e66d1f074623dc2Victoria Lease            throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
7374fab68b5324e1f9b6765cdc33e66d1f074623dc2Victoria Lease        }
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
74037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    /**
74137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Return the minimum resolution level required to use the specified location provider.
74237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
74337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param provider the name of the location provider
74437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @return minimum resolution level required for provider
74537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     */
74637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private int getMinimumResolutionLevelForProviderUse(String provider) {
7478dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease        if (LocationManager.GPS_PROVIDER.equals(provider) ||
7488dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease                LocationManager.PASSIVE_PROVIDER.equals(provider)) {
7498dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease            // gps and passive providers require FINE permission
75037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            return RESOLUTION_LEVEL_FINE;
7518dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease        } else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
7528dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease                LocationManager.FUSED_PROVIDER.equals(provider)) {
7538dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease            // network and fused providers are ok with COARSE or FINE
75437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            return RESOLUTION_LEVEL_COARSE;
755941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu        } else {
756941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu            // mock providers
757941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu            LocationProviderInterface lp = mMockProviders.get(provider);
758941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu            if (lp != null) {
759941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                ProviderProperties properties = lp.getProperties();
760941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                if (properties != null) {
761941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                    if (properties.mRequiresSatellite) {
762941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                        // provider requiring satellites require FINE permission
76337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                        return RESOLUTION_LEVEL_FINE;
764941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                    } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
765941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                        // provider requiring network and or cell require COARSE or FINE
76637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                        return RESOLUTION_LEVEL_COARSE;
767941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                    }
768941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                }
769941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu            }
7708dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease        }
77137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
772da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease    }
773da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease
77437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    /**
77537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Throw SecurityException if specified resolution level is insufficient to use the named
77637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * location provider.
77737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
77837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param allowedResolutionLevel resolution level allowed to caller
77937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param providerName the name of the location provider
78037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     */
78137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
78237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            String providerName) {
78337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
78437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        if (allowedResolutionLevel < requiredResolutionLevel) {
78537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            switch (requiredResolutionLevel) {
78637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                case RESOLUTION_LEVEL_FINE:
78737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    throw new SecurityException("\"" + providerName + "\" location provider " +
78837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                            "requires ACCESS_FINE_LOCATION permission.");
78937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                case RESOLUTION_LEVEL_COARSE:
79037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    throw new SecurityException("\"" + providerName + "\" location provider " +
79137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                            "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
79237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                default:
79337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    throw new SecurityException("Insufficient permission for \"" + providerName +
79437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                            "\" location provider.");
795da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease            }
796da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease        }
7978dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease    }
7988dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease
7996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    /**
8006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * Returns all providers by name, including passive, but excluding
8010d21e2161f8542db0a54bf80b74b7fd33afef6f6Laurent Tu     * fused, also including ones that are not permitted to
8020d21e2161f8542db0a54bf80b74b7fd33afef6f6Laurent Tu     * be accessed by the calling activity or are currently disabled.
8036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     */
804e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<String> getAllProviders() {
8066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        ArrayList<String> out;
8076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        synchronized (mLock) {
8086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            out = new ArrayList<String>(mProviders.size());
8096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (LocationProviderInterface provider : mProviders) {
8106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                String name = provider.getName();
8116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                if (LocationManager.FUSED_PROVIDER.equals(name)) {
8126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    continue;
8136fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                }
8146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                out.add(name);
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "getAllProviders()=" + out);
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return out;
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    /**
8236fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * Return all providers by name, that match criteria and are optionally
8246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * enabled.
8256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * Can return passive provider, but never returns fused provider.
8266fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     */
827e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
82803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
82937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
8306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        ArrayList<String> out;
831269518e83efc01b387235d6194dcf93726e384ffVictoria Lease        int callingUserId = UserHandle.getCallingUserId();
832269518e83efc01b387235d6194dcf93726e384ffVictoria Lease        long identity = Binder.clearCallingIdentity();
833b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        try {
834b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            synchronized (mLock) {
835b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                out = new ArrayList<String>(mProviders.size());
836b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                for (LocationProviderInterface provider : mProviders) {
837b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    String name = provider.getName();
838b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    if (LocationManager.FUSED_PROVIDER.equals(name)) {
8398dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease                        continue;
8408dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease                    }
84137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
842269518e83efc01b387235d6194dcf93726e384ffVictoria Lease                        if (enabledOnly && !isAllowedBySettingsLocked(name, callingUserId)) {
843b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                            continue;
844b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        }
845b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        if (criteria != null && !LocationProvider.propertiesMeetCriteria(
846b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                                name, provider.getProperties(), criteria)) {
847b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                            continue;
848b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        }
849b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        out.add(name);
8508dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease                    }
85103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                }
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
853b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        } finally {
854b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            Binder.restoreCallingIdentity(identity);
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
85603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
8576fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "getProviders()=" + out);
8586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        return out;
85903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
86003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
86103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    /**
8626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * Return the name of the best provider given a Criteria object.
8636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * This method has been deprecated from the public API,
8648dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease     * and the whole LocationProvider (including #meetsCriteria)
8656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * has been deprecated as well. So this method now uses
8666fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * some simplified logic.
86703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood     */
868e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
86903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public String getBestProvider(Criteria criteria, boolean enabledOnly) {
8706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        String result = null;
87103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
8726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        List<String> providers = getProviders(criteria, enabledOnly);
8738dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease        if (!providers.isEmpty()) {
8746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            result = pickBest(providers);
8756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
8766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return result;
87703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
8786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        providers = getProviders(null, enabledOnly);
8798dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease        if (!providers.isEmpty()) {
8806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            result = pickBest(providers);
8816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
8826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return result;
88303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
88403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
8856fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
8866fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        return null;
8876fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
88803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
8896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private String pickBest(List<String> providers) {
8901925e290e7ac2801311cb4e732d1bc5a5f3e0c44Victoria Lease        if (providers.contains(LocationManager.GPS_PROVIDER)) {
8916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return LocationManager.GPS_PROVIDER;
8921925e290e7ac2801311cb4e732d1bc5a5f3e0c44Victoria Lease        } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
8931925e290e7ac2801311cb4e732d1bc5a5f3e0c44Victoria Lease            return LocationManager.NETWORK_PROVIDER;
8946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else {
8956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return providers.get(0);
89603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
89703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
89803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
899e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
90003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public boolean providerMeetsCriteria(String provider, Criteria criteria) {
90103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
90203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        if (p == null) {
90303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            throw new IllegalArgumentException("provider=" + provider);
90403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
9056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
9066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        boolean result = LocationProvider.propertiesMeetCriteria(
9076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                p.getName(), p.getProperties(), criteria);
9086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result);
9096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        return result;
91003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
91103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateProvidersLocked() {
9130c5a04014d3833c9a82772a832d3bc6410fc52acBrad Fitzpatrick        boolean changesMade = false;
91415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        for (int i = mProviders.size() - 1; i >= 0; i--) {
915d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            LocationProviderInterface p = mProviders.get(i);
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean isEnabled = p.isEnabled();
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = p.getName();
918269518e83efc01b387235d6194dcf93726e384ffVictoria Lease            boolean shouldBeEnabled = isAllowedBySettingsLocked(name, mCurrentUserId);
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isEnabled && !shouldBeEnabled) {
920b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                updateProviderListenersLocked(name, false, mCurrentUserId);
9210c5a04014d3833c9a82772a832d3bc6410fc52acBrad Fitzpatrick                changesMade = true;
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (!isEnabled && shouldBeEnabled) {
923b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                updateProviderListenersLocked(name, true, mCurrentUserId);
9240c5a04014d3833c9a82772a832d3bc6410fc52acBrad Fitzpatrick                changesMade = true;
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9260c5a04014d3833c9a82772a832d3bc6410fc52acBrad Fitzpatrick        }
9270c5a04014d3833c9a82772a832d3bc6410fc52acBrad Fitzpatrick        if (changesMade) {
9285ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn            mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
9295ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn                    UserHandle.ALL);
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
933b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease    private void updateProviderListenersLocked(String provider, boolean enabled, int userId) {
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int listeners = 0;
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
936d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
9376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (p == null) return;
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<Receiver> deadReceivers = null;
940e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (records != null) {
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int N = records.size();
9446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (int i = 0; i < N; i++) {
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                UpdateRecord record = records.get(i);
946269518e83efc01b387235d6194dcf93726e384ffVictoria Lease                if (UserHandle.getUserId(record.mReceiver.mUid) == userId) {
947b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    // Sends a notification message to the receiver
948b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
949b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        if (deadReceivers == null) {
950b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                            deadReceivers = new ArrayList<Receiver>();
951b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        }
952b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        deadReceivers.add(record.mReceiver);
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
954b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    listeners++;
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (deadReceivers != null) {
9606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (int i = deadReceivers.size() - 1; i >= 0; i--) {
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeUpdatesLocked(deadReceivers.get(i));
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
964e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (enabled) {
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.enable();
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (listeners > 0) {
9686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                applyRequirementsLocked(provider);
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.disable();
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void applyRequirementsLocked(String provider) {
9766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        LocationProviderInterface p = mProvidersByName.get(provider);
9776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (p == null) return;
9786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
9806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        WorkSource worksource = new WorkSource();
9816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        ProviderRequest providerRequest = new ProviderRequest();
9826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (records != null) {
9846fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (UpdateRecord record : records) {
985269518e83efc01b387235d6194dcf93726e384ffVictoria Lease                if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
986b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    LocationRequest locationRequest = record.mRequest;
987b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    providerRequest.locationRequests.add(locationRequest);
988b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    if (locationRequest.getInterval() < providerRequest.interval) {
989b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        providerRequest.reportLocation = true;
990b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        providerRequest.interval = locationRequest.getInterval();
991b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    }
9927e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn                }
9937e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            }
9946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
9956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (providerRequest.reportLocation) {
9966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // calculate who to blame for power
9976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // This is somewhat arbitrary. We pick a threshold interval
9986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // that is slightly higher that the minimum interval, and
9996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // spread the blame across all applications with a request
10006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // under that threshold.
10016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
10026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                for (UpdateRecord record : records) {
1003269518e83efc01b387235d6194dcf93726e384ffVictoria Lease                    if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
1004b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        LocationRequest locationRequest = record.mRequest;
1005b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        if (locationRequest.getInterval() <= thresholdInterval) {
1006b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                            worksource.add(record.mReceiver.mUid);
1007b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        }
10086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    }
10097e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn                }
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
10136fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
10146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        p.setRequest(providerRequest, worksource);
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class UpdateRecord {
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String mProvider;
10196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final LocationRequest mRequest;
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Receiver mReceiver;
10212f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Location mLastFixBroadcast;
10222f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        long mLastStatusBroadcast;
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Note: must be constructed with lock held.
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
10276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProvider = provider;
10296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mRequest = request;
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mReceiver = receiver;
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (records == null) {
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                records = new ArrayList<UpdateRecord>();
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRecordsByProvider.put(provider, records);
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!records.contains(this)) {
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                records.add(this);
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Method to be called when a record will no longer be used.  Calling this multiple times
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * must have the same effect as calling it once.
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
10466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        void disposeLocked(boolean removeReceiver) {
10476fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // remove from mRecordsByProvider
10486fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
10496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (globalRecords != null) {
10506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                globalRecords.remove(this);
10516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
10526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
10536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (!removeReceiver) return;  // the caller will handle the rest
10546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
10556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // remove from Receiver#mUpdateRecords
10566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
10576fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (receiverRecords != null) {
10586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                receiverRecords.remove(this.mProvider);
10596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
10606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // and also remove the Receiver if it has no more update records
10616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                if (removeReceiver && receiverRecords.size() == 0) {
10626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    removeUpdatesLocked(mReceiver);
10636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                }
10643a76fd627945c1df59aa0318867401e0e53da022Mike Lockwood            }
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
10696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            StringBuilder s = new StringBuilder();
10706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append("UpdateRecord[");
10716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append(mProvider);
10726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append(' ').append(mReceiver.mPackageName).append('(');
10736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append(mReceiver.mUid).append(')');
10746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append(' ').append(mRequest);
10756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append(']');
10766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return s.toString();
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private Receiver getReceiver(ILocationListener listener, int pid, int uid, String packageName) {
10812f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        IBinder binder = listener.asBinder();
10822f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver receiver = mReceivers.get(binder);
10832f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (receiver == null) {
10846fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            receiver = new Receiver(listener, null, pid, uid, packageName);
10852f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            mReceivers.put(binder, receiver);
10862f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
10872f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            try {
10886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                receiver.getListener().asBinder().linkToDeath(receiver, 0);
10892f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            } catch (RemoteException e) {
10908a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.e(TAG, "linkToDeath failed:", e);
10912f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                return null;
10922f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
10932f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
10942f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        return receiver;
10952f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
10962f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
10976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private Receiver getReceiver(PendingIntent intent, int pid, int uid, String packageName) {
10982f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver receiver = mReceivers.get(intent);
10992f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (receiver == null) {
11006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            receiver = new Receiver(null, intent, pid, uid, packageName);
11012f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            mReceivers.put(intent, receiver);
11022f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
11032f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        return receiver;
11042f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
11052f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
110637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    /**
110737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
110837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * and consistency requirements.
110937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
111037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param request the LocationRequest from which to create a sanitized version
111137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param shouldBeCoarse whether the sanitized version should be held to coarse resolution
111237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * constraints
111337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param fastestCoarseIntervalMS minimum interval allowed for coarse resolution
111437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @return a version of request that meets the given resolution and consistency requirements
111537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @hide
111637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     */
111737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel) {
111837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        LocationRequest sanitizedRequest = new LocationRequest(request);
111937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
112037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            switch (sanitizedRequest.getQuality()) {
112109016ab4dd056a16809419d612cb865a14980880Victoria Lease                case LocationRequest.ACCURACY_FINE:
112237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
112309016ab4dd056a16809419d612cb865a14980880Victoria Lease                    break;
112409016ab4dd056a16809419d612cb865a14980880Victoria Lease                case LocationRequest.POWER_HIGH:
112537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
112609016ab4dd056a16809419d612cb865a14980880Victoria Lease                    break;
112709016ab4dd056a16809419d612cb865a14980880Victoria Lease            }
112809016ab4dd056a16809419d612cb865a14980880Victoria Lease            // throttle
112937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
113037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
113109016ab4dd056a16809419d612cb865a14980880Victoria Lease            }
113237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
113337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
113409016ab4dd056a16809419d612cb865a14980880Victoria Lease            }
113574fa7eabda3d0c1a85e0b568e3fc4230ed4fe7a4Nick Pelly        }
11364e31c4fffbc42b4c2b5dca6431cfeef9e078f5b4Nick Pelly        // make getFastestInterval() the minimum of interval and fastest interval
113737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
11384e31c4fffbc42b4c2b5dca6431cfeef9e078f5b4Nick Pelly            request.setFastestInterval(request.getInterval());
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
114037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        return sanitizedRequest;
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void checkPackageName(String packageName) {
1144e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        if (packageName == null) {
11456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            throw new SecurityException("invalid package name: " + packageName);
1146e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        }
11476fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        int uid = Binder.getCallingUid();
1148e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        String[] packages = mPackageManager.getPackagesForUid(uid);
1149e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        if (packages == null) {
1150e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly            throw new SecurityException("invalid UID " + uid);
1151e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        }
1152e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        for (String pkg : packages) {
1153e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly            if (packageName.equals(pkg)) return;
1154e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        }
11556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        throw new SecurityException("invalid package name: " + packageName);
1156e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    }
1157e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
11586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void checkPendingIntent(PendingIntent intent) {
11596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (intent == null) {
11606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            throw new IllegalArgumentException("invalid pending intent: " + intent);
11616c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn        }
11626c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn    }
11636c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn
11646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private Receiver checkListenerOrIntent(ILocationListener listener, PendingIntent intent,
11656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            int pid, int uid, String packageName) {
11666fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (intent == null && listener == null) {
11676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            throw new IllegalArgumentException("need eiter listener or intent");
11686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else if (intent != null && listener != null) {
11696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            throw new IllegalArgumentException("cannot register both listener and intent");
11706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else if (intent != null) {
11716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            checkPendingIntent(intent);
11726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return getReceiver(intent, pid, uid, packageName);
11736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else {
11746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return getReceiver(listener, pid, uid, packageName);
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
11796fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
11806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            PendingIntent intent, String packageName) {
11816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (request == null) request = DEFAULT_LOCATION_REQUEST;
11826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkPackageName(packageName);
118337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
118437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
118537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                request.getProvider());
118637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final int pid = Binder.getCallingPid();
11896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final int uid = Binder.getCallingUid();
11906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Receiver recevier = checkListenerOrIntent(listener, intent, pid, uid, packageName);
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11922b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        // providers may use public location API's, need to clear identity
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identity = Binder.clearCallingIdentity();
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
11956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            synchronized (mLock) {
119637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
11972d4d1bf14b531de9d4238b1e41b53c77f8976405Mike Lockwood            }
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(identity);
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
12046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            int pid, int uid, String packageName) {
12056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // Figure out the provider. Either its explicitly request (legacy use cases), or
12066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // use the fused provider
12076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (request == null) request = DEFAULT_LOCATION_REQUEST;
12086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        String name = request.getProvider();
120909016ab4dd056a16809419d612cb865a14980880Victoria Lease        if (name == null) {
121009016ab4dd056a16809419d612cb865a14980880Victoria Lease            throw new IllegalArgumentException("provider name must not be null");
121109016ab4dd056a16809419d612cb865a14980880Victoria Lease        }
12126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        LocationProviderInterface provider = mProvidersByName.get(name);
12136fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (provider == null) {
12146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            throw new IllegalArgumentException("provider doesn't exisit: " + provider);
12156fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
12166fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
12177ff30113de68539ec840c524b8f1561f938f96c5Dianne Hackborn        if (D) Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
12187ff30113de68539ec840c524b8f1561f938f96c5Dianne Hackborn                + " " + name + " " + request + " from " + packageName + "(" + uid + ")");
12196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
12206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        UpdateRecord record = new UpdateRecord(name, request, receiver);
12216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
12226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (oldRecord != null) {
12236fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            oldRecord.disposeLocked(false);
12246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
12256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1226269518e83efc01b387235d6194dcf93726e384ffVictoria Lease        boolean isProviderEnabled = isAllowedBySettingsLocked(name, UserHandle.getUserId(uid));
12276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (isProviderEnabled) {
12286fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            applyRequirementsLocked(name);
12296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else {
12306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // Notify the listener that updates are currently disabled
12316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            receiver.callProviderEnabledLocked(name, false);
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1235e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
12366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void removeUpdates(ILocationListener listener, PendingIntent intent,
12376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            String packageName) {
12386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkPackageName(packageName);
123937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease
12406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final int pid = Binder.getCallingPid();
12416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final int uid = Binder.getCallingUid();
12426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Receiver receiver = checkListenerOrIntent(listener, intent, pid, uid, packageName);
12436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
12442b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        // providers may use public location API's, need to clear identity
12456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        long identity = Binder.clearCallingIdentity();
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
12472f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
12486fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                removeUpdatesLocked(receiver);
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } finally {
12516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            Binder.restoreCallingIdentity(identity);
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void removeUpdatesLocked(Receiver receiver) {
12567ff30113de68539ec840c524b8f1561f938f96c5Dianne Hackborn        if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
12596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
12606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            synchronized (receiver) {
12616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                if (receiver.mPendingBroadcasts > 0) {
12626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    decrementPendingBroadcasts();
12636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    receiver.mPendingBroadcasts = 0;
1264080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                }
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12666fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // Record which providers were associated with this listener
12696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        HashSet<String> providers = new HashSet<String>();
12706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
12716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (oldRecords != null) {
12726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // Call dispose() on the obsolete update records.
12736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (UpdateRecord record : oldRecords.values()) {
12746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                record.disposeLocked(false);
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // Accumulate providers
12776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            providers.addAll(oldRecords.keySet());
12786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // update provider
12816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        for (String provider : providers) {
12826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // If provider is already disabled, don't need to do anything
1283269518e83efc01b387235d6194dcf93726e384ffVictoria Lease            if (!isAllowedBySettingsLocked(provider, mCurrentUserId)) {
12846fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                continue;
12856fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12876fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            applyRequirementsLocked(provider);
12886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
12896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
12924035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    public Location getLastLocation(LocationRequest request, String packageName) {
12936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "getLastLocation: " + request);
12946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (request == null) request = DEFAULT_LOCATION_REQUEST;
129537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
12964035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        checkPackageName(packageName);
129737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
129837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                request.getProvider());
129937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        // no need to sanitize this request, as only the provider name is used
13004035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
1301269518e83efc01b387235d6194dcf93726e384ffVictoria Lease        long identity = Binder.clearCallingIdentity();
1302b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        try {
1303b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            if (mBlacklist.isBlacklisted(packageName)) {
1304b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
1305b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        packageName);
130609016ab4dd056a16809419d612cb865a14980880Victoria Lease                return null;
130709016ab4dd056a16809419d612cb865a14980880Victoria Lease            }
1308b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease
1309b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            synchronized (mLock) {
1310b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                // Figure out the provider. Either its explicitly request (deprecated API's),
1311b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                // or use the fused provider
1312b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                String name = request.getProvider();
1313b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (name == null) name = LocationManager.FUSED_PROVIDER;
1314b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                LocationProviderInterface provider = mProvidersByName.get(name);
1315b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (provider == null) return null;
1316b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease
1317269518e83efc01b387235d6194dcf93726e384ffVictoria Lease                if (!isAllowedBySettingsLocked(name, mCurrentUserId)) return null;
1318b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease
1319b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                Location location = mLastLocation.get(name);
1320b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (location == null) {
1321b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    return null;
1322b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                }
132337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
1324b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
1325b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    if (noGPSLocation != null) {
1326b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        return mLocationFudger.getOrCreate(noGPSLocation);
1327b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    }
132837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                } else {
132937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    return location;
133009016ab4dd056a16809419d612cb865a14980880Victoria Lease                }
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1332b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            return null;
1333b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        } finally {
1334b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            Binder.restoreCallingIdentity(identity);
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1338e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
13396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
13406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            String packageName) {
13416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (request == null) request = DEFAULT_LOCATION_REQUEST;
134237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
134337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
13446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkPendingIntent(intent);
13456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkPackageName(packageName);
134637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
134737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                request.getProvider());
134837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
13496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
135037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
13516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
13522b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        // geo-fence manager uses the public location API, need to clear identity
13532b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        int uid = Binder.getCallingUid();
135456e675b3a1c351de34de68a149762d3ad1b308c5Victoria Lease        if (UserHandle.getUserId(uid) != UserHandle.USER_OWNER) {
135556e675b3a1c351de34de68a149762d3ad1b308c5Victoria Lease            // temporary measure until geofences work for secondary users
135656e675b3a1c351de34de68a149762d3ad1b308c5Victoria Lease            Log.w(TAG, "proximity alerts are currently available only to the primary user");
135756e675b3a1c351de34de68a149762d3ad1b308c5Victoria Lease            return;
135856e675b3a1c351de34de68a149762d3ad1b308c5Victoria Lease        }
13592b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        long identity = Binder.clearCallingIdentity();
13602b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        try {
136137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            mGeofenceManager.addFence(sanitizedRequest, geofence, intent, uid, packageName);
13622b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        } finally {
13632b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly            Binder.restoreCallingIdentity(identity);
13642b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        }
13656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
13666fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
13676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
13686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
136937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForGeofenceUse(getCallerAllowedResolutionLevel());
13706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkPendingIntent(intent);
13716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkPackageName(packageName);
13726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
13736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
13746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
13752b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        // geo-fence manager uses the public location API, need to clear identity
13762b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        long identity = Binder.clearCallingIdentity();
13772b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        try {
13782b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly            mGeofenceManager.removeFence(geofence, intent);
13792b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        } finally {
13802b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly            Binder.restoreCallingIdentity(identity);
13812b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        }
13826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
13836fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
13846fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
13856fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean addGpsStatusListener(IGpsStatusListener listener) {
138715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mGpsStatusProvider == null) {
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
139037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
139137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                LocationManager.GPS_PROVIDER);
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
139415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            mGpsStatusProvider.addGpsStatusListener(listener);
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
13968a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "mGpsStatusProvider.addGpsStatusListener failed", e);
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1402e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeGpsStatusListener(IGpsStatusListener listener) {
14042f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
140515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            try {
140615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                mGpsStatusProvider.removeGpsStatusListener(listener);
140715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            } catch (Exception e) {
14088a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.e(TAG, "mGpsStatusProvider.removeGpsStatusListener failed", e);
140915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1413e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendExtraCommand(String provider, String command, Bundle extras) {
1415c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood        if (provider == null) {
1416c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood            // throw NullPointerException to remain compatible with previous implementation
1417c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood            throw new NullPointerException();
1418c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood        }
141937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
142037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                provider);
1421c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // and check for ACCESS_LOCATION_EXTRA_COMMANDS
1423b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood        if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14282f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
1429d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            LocationProviderInterface p = mProvidersByName.get(provider);
14306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (p == null) return false;
1431e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
1432d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            return p.sendExtraCommand(command, extras);
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1436e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
14376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public boolean sendNiResponse(int notifId, int userResponse) {
143818ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood        if (Binder.getCallingUid() != Process.myUid()) {
143918ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood            throw new SecurityException(
144018ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood                    "calling sendNiResponse from outside of the system is not allowed");
144118ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood        }
144222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        try {
144322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
14446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } catch (RemoteException e) {
14458a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
144622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            return false;
144722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        }
144822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    }
144922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1451628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood     * @return null if the provider does not exist
1452f2db9fb0f877057a9ef56908d54f3c95fc3fd552Alexey Tarasov     * @throws SecurityException if the provider is not allowed to be
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * accessed by the caller
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1455e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
14566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public ProviderProperties getProviderProperties(String provider) {
1457b7f9d254978b285bf04613f6e69a1afa89240ca9Laurent Tu        if (mProvidersByName.get(provider) == null) {
1458b7f9d254978b285bf04613f6e69a1afa89240ca9Laurent Tu          return null;
1459b7f9d254978b285bf04613f6e69a1afa89240ca9Laurent Tu        }
1460b7f9d254978b285bf04613f6e69a1afa89240ca9Laurent Tu
146137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
146237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                provider);
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        LocationProviderInterface p;
14656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        synchronized (mLock) {
14666fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            p = mProvidersByName.get(provider);
14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (p == null) return null;
14706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        return p.getProperties();
14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1473e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isProviderEnabled(String provider) {
147537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
147637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                provider);
14776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
14786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1479269518e83efc01b387235d6194dcf93726e384ffVictoria Lease        long identity = Binder.clearCallingIdentity();
1480b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        try {
1481b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            synchronized (mLock) {
1482b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                LocationProviderInterface p = mProvidersByName.get(provider);
1483b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (p == null) return false;
14846fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1485269518e83efc01b387235d6194dcf93726e384ffVictoria Lease                return isAllowedBySettingsLocked(provider, mCurrentUserId);
1486b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            }
1487b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        } finally {
1488b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            Binder.restoreCallingIdentity(identity);
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void checkCallerIsProvider() {
1493275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
14946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                == PackageManager.PERMISSION_GRANTED) {
14952eeeec248a38ff33999c83f4b8d5bab7d50e79d2Nick Pelly            return;
14962eeeec248a38ff33999c83f4b8d5bab7d50e79d2Nick Pelly        }
14972eeeec248a38ff33999c83f4b8d5bab7d50e79d2Nick Pelly
14986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // Previously we only used the INSTALL_LOCATION_PROVIDER
14996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // check. But that is system or signature
15006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // protection level which is not flexible enough for
15016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // providers installed oustide the system image. So
15026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // also allow providers with a UID matching the
15036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // currently bound package name
15044e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood
15056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        int uid = Binder.getCallingUid();
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (mGeocodeProvider != null) {
15086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (doesPackageHaveUid(uid, mGeocodeProvider.getConnectedPackageName())) return;
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        for (LocationProviderProxy proxy : mProxyProviders) {
15116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (doesPackageHaveUid(uid, proxy.getConnectedPackageName())) return;
15126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
15136fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
15146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                "or UID of a currently bound location provider");
15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15176fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private boolean doesPackageHaveUid(int uid, String packageName) {
15186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (packageName == null) {
15196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return false;
15204a7b65e0d544ef1feff8e1e5789f469f89ebb85cMike Lockwood        }
15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
15226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            ApplicationInfo appInfo = mPackageManager.getApplicationInfo(packageName, 0);
15236fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (appInfo.uid != uid) {
15246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                return false;
15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15266fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } catch (NameNotFoundException e) {
15276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return false;
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        return true;
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
15336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void reportLocation(Location location, boolean passive) {
15346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkCallerIsProvider();
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (!location.isComplete()) {
15376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            Log.w(TAG, "Dropping incomplete location: " + location);
15386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return;
15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location);
15426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location);
15436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        m.arg1 = (passive ? 1 : 0);
15446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mLocationHandler.sendMessageAtFrontOfQueue(m);
15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15476fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
154875defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu    private static boolean shouldBroadcastSafe(
154975defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu            Location loc, Location lastLoc, UpdateRecord record, long now) {
15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Always broadcast the first update
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (lastLoc == null) {
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1555f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly        // Check whether sufficient time has passed
15566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        long minTime = record.mRequest.getFastestInterval();
15574118012da9a22694b3353040a485f8cdc27e2f17Philip Milne        long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos()) / 1000000L;
15586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Check whether sufficient distance has been traveled
15636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        double minDistance = record.mRequest.getSmallestDisplacement();
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (minDistance > 0.0) {
15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (loc.distanceTo(lastLoc) <= minDistance) {
15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
157075defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu        // Check whether sufficient number of udpates is left
157175defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu        if (record.mRequest.getNumUpdates() <= 0) {
157275defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu            return false;
157375defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu        }
157475defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu
157575defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu        // Check whether the expiry date has passed
157675defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu        if (record.mRequest.getExpireAt() < now) {
157775defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu            return false;
157875defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu        }
157975defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu
15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1583a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood    private void handleLocationChangedLocked(Location location, boolean passive) {
15844e31c4fffbc42b4c2b5dca6431cfeef9e078f5b4Nick Pelly        if (D) Log.d(TAG, "incoming location: " + location);
15854e31c4fffbc42b4c2b5dca6431cfeef9e078f5b4Nick Pelly
15866fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        long now = SystemClock.elapsedRealtime();
1587a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
158960ec50a850ac7265b662df3c872583b6ef581ef8Laurent Tu        // Skip if the provider is unknown.
1590d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
15916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (p == null) return;
15926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
15936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // Update last known locations
159409016ab4dd056a16809419d612cb865a14980880Victoria Lease        Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
159509016ab4dd056a16809419d612cb865a14980880Victoria Lease        Location lastNoGPSLocation = null;
15966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Location lastLocation = mLastLocation.get(provider);
15974e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        if (lastLocation == null) {
15986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            lastLocation = new Location(provider);
15996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mLastLocation.put(provider, lastLocation);
160009016ab4dd056a16809419d612cb865a14980880Victoria Lease        } else {
160109016ab4dd056a16809419d612cb865a14980880Victoria Lease            lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
160209016ab4dd056a16809419d612cb865a14980880Victoria Lease            if (noGPSLocation == null && lastNoGPSLocation != null) {
160309016ab4dd056a16809419d612cb865a14980880Victoria Lease                // New location has no no-GPS location: adopt last no-GPS location. This is set
160409016ab4dd056a16809419d612cb865a14980880Victoria Lease                // directly into location because we do not want to notify COARSE clients.
160509016ab4dd056a16809419d612cb865a14980880Victoria Lease                location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
160609016ab4dd056a16809419d612cb865a14980880Victoria Lease            }
16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        lastLocation.set(location);
16099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
161060ec50a850ac7265b662df3c872583b6ef581ef8Laurent Tu        // Skip if there are no UpdateRecords for this provider.
161160ec50a850ac7265b662df3c872583b6ef581ef8Laurent Tu        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
161260ec50a850ac7265b662df3c872583b6ef581ef8Laurent Tu        if (records == null || records.size() == 0) return;
161360ec50a850ac7265b662df3c872583b6ef581ef8Laurent Tu
161409016ab4dd056a16809419d612cb865a14980880Victoria Lease        // Fetch coarse location
161509016ab4dd056a16809419d612cb865a14980880Victoria Lease        Location coarseLocation = null;
161609016ab4dd056a16809419d612cb865a14980880Victoria Lease        if (noGPSLocation != null && !noGPSLocation.equals(lastNoGPSLocation)) {
161709016ab4dd056a16809419d612cb865a14980880Victoria Lease            coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
161809016ab4dd056a16809419d612cb865a14980880Victoria Lease        }
161909016ab4dd056a16809419d612cb865a14980880Victoria Lease
16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Fetch latest status update time
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long newStatusUpdateTime = p.getStatusUpdateTime();
16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16237ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood       // Get latest status
16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bundle extras = new Bundle();
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int status = p.getStatus(extras);
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<Receiver> deadReceivers = null;
16286fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        ArrayList<UpdateRecord> deadUpdateRecords = null;
1629e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Broadcast location or status to all listeners
16316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        for (UpdateRecord r : records) {
16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Receiver receiver = r.mReceiver;
163303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            boolean receiverDead = false;
16344035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
1635269518e83efc01b387235d6194dcf93726e384ffVictoria Lease            int receiverUserId = UserHandle.getUserId(receiver.mUid);
1636269518e83efc01b387235d6194dcf93726e384ffVictoria Lease            if (receiverUserId != mCurrentUserId) {
1637b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (D) {
1638269518e83efc01b387235d6194dcf93726e384ffVictoria Lease                    Log.d(TAG, "skipping loc update for background user " + receiverUserId +
1639b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                            " (current user: " + mCurrentUserId + ", app: " +
1640b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                            receiver.mPackageName + ")");
1641b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                }
1642b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                continue;
1643b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            }
1644b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease
16454035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            if (mBlacklist.isBlacklisted(receiver.mPackageName)) {
16464035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
16474035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                        receiver.mPackageName);
16484035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                continue;
16494035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            }
16504035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
165109016ab4dd056a16809419d612cb865a14980880Victoria Lease            Location notifyLocation = null;
165237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
165337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                notifyLocation = coarseLocation;  // use coarse location
16546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            } else {
165537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                notifyLocation = lastLocation;  // use fine location
16566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
165709016ab4dd056a16809419d612cb865a14980880Victoria Lease            if (notifyLocation != null) {
165809016ab4dd056a16809419d612cb865a14980880Victoria Lease                Location lastLoc = r.mLastFixBroadcast;
165975defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu                if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) {
166009016ab4dd056a16809419d612cb865a14980880Victoria Lease                    if (lastLoc == null) {
166109016ab4dd056a16809419d612cb865a14980880Victoria Lease                        lastLoc = new Location(notifyLocation);
166209016ab4dd056a16809419d612cb865a14980880Victoria Lease                        r.mLastFixBroadcast = lastLoc;
166309016ab4dd056a16809419d612cb865a14980880Victoria Lease                    } else {
166409016ab4dd056a16809419d612cb865a14980880Victoria Lease                        lastLoc.set(notifyLocation);
166509016ab4dd056a16809419d612cb865a14980880Victoria Lease                    }
166609016ab4dd056a16809419d612cb865a14980880Victoria Lease                    if (!receiver.callLocationChangedLocked(notifyLocation)) {
166709016ab4dd056a16809419d612cb865a14980880Victoria Lease                        Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
166809016ab4dd056a16809419d612cb865a14980880Victoria Lease                        receiverDead = true;
166909016ab4dd056a16809419d612cb865a14980880Victoria Lease                    }
167075defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu                    r.mRequest.decrementNumUpdates();
16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16742f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            long prevStatusUpdateTime = r.mLastStatusBroadcast;
16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((newStatusUpdateTime > prevStatusUpdateTime) &&
167609016ab4dd056a16809419d612cb865a14980880Victoria Lease                    (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16782f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                r.mLastStatusBroadcast = newStatusUpdateTime;
16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!receiver.callStatusChangedLocked(provider, status, extras)) {
168003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    receiverDead = true;
16818a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
168203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                }
168303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            }
168403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
16856fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // track expired records
168675defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu            if (r.mRequest.getNumUpdates() <= 0 || r.mRequest.getExpireAt() < now) {
16876fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                if (deadUpdateRecords == null) {
16886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    deadUpdateRecords = new ArrayList<UpdateRecord>();
16896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                }
16906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                deadUpdateRecords.add(r);
16916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
16926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // track dead receivers
16936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (receiverDead) {
169403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                if (deadReceivers == null) {
169503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    deadReceivers = new ArrayList<Receiver>();
169603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                }
169703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                if (!deadReceivers.contains(receiver)) {
169803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    deadReceivers.add(receiver);
16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
17009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1702e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
17036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // remove dead records and receivers outside the loop
17049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (deadReceivers != null) {
17056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (Receiver receiver : deadReceivers) {
17066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                removeUpdatesLocked(receiver);
17076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
17086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
17096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (deadUpdateRecords != null) {
17106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (UpdateRecord r : deadUpdateRecords) {
17116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                r.disposeLocked(true);
17129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class LocationWorkerHandler extends Handler {
17179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
17189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void handleMessage(Message msg) {
17196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            switch (msg.what) {
17206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                case MSG_LOCATION_CHANGED:
17216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    handleLocationChanged((Location) msg.obj, msg.arg1 == 1);
17226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    break;
17236fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
17246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
17256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
172698cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood
17276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void handleLocationChanged(Location location, boolean passive) {
17286fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        String provider = location.getProvider();
17296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
17306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (!passive) {
17316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // notify passive provider of the new location
17326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mPassiveProvider.updateLocation(location);
17336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
17346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
17356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        synchronized (mLock) {
1736269518e83efc01b387235d6194dcf93726e384ffVictoria Lease            if (isAllowedBySettingsLocked(provider, mCurrentUserId)) {
17376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                handleLocationChangedLocked(location, passive);
17389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final PackageMonitor mPackageMonitor = new PackageMonitor() {
17430528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        @Override
17446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        public void onPackageDisappeared(String packageName, int reason) {
17456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // remove all receivers associated with this package name
17466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            synchronized (mLock) {
17476fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                ArrayList<Receiver> deadReceivers = null;
17486fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
17496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                for (Receiver receiver : mReceivers.values()) {
17506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    if (receiver.mPackageName.equals(packageName)) {
17516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                        if (deadReceivers == null) {
17526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                            deadReceivers = new ArrayList<Receiver>();
17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
17546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                        deadReceivers.add(receiver);
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // perform removal outside of mReceivers loop
17596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                if (deadReceivers != null) {
17606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    for (Receiver receiver : deadReceivers) {
17616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                        removeUpdatesLocked(receiver);
17629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17660528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    };
17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Wake locks
17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17700528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private void incrementPendingBroadcasts() {
17710528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        synchronized (mWakeLock) {
17720528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (mPendingBroadcasts++ == 0) {
17730528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                try {
17740528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    mWakeLock.acquire();
17750528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    log("Acquired wakelock");
17760528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                } catch (Exception e) {
17770528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // This is to catch a runtime exception thrown when we try to release an
17780528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // already released lock.
17798a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.e(TAG, "exception in acquireWakeLock()", e);
17800528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                }
17810528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
178248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
178348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
178448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
178548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private void decrementPendingBroadcasts() {
17860528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        synchronized (mWakeLock) {
178748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (--mPendingBroadcasts == 0) {
17880528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                try {
17890528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // Release wake lock
17900528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    if (mWakeLock.isHeld()) {
17910528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                        mWakeLock.release();
17920528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                        log("Released wakelock");
17930528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    } else {
17940528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                        log("Can't release wakelock again!");
17950528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    }
17960528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                } catch (Exception e) {
17970528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // This is to catch a runtime exception thrown when we try to release an
17980528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // already released lock.
17998a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.e(TAG, "exception in releaseWakeLock()", e);
18000528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                }
180148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
180248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
180348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
180448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Geocoder
18069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1807e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
1808e15735a9e0c0b1448b68f2d6b3247404fc1df417Mike Lockwood    public boolean geocoderIsPresent() {
180901ac80b715881db22bde8b31633dd8a4dc375389Mark Vandevoorde        return mGeocodeProvider != null;
181001ac80b715881db22bde8b31633dd8a4dc375389Mark Vandevoorde    }
181101ac80b715881db22bde8b31633dd8a4dc375389Mark Vandevoorde
1812e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
18139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String getFromLocation(double latitude, double longitude, int maxResults,
181434901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwood            GeocoderParams params, List<Address> addrs) {
1815a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        if (mGeocodeProvider != null) {
1816628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood            return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
1817628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                    params, addrs);
18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1819a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        return null;
18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1822a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood
1823e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
18249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String getFromLocationName(String locationName,
1825a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            double lowerLeftLatitude, double lowerLeftLongitude,
1826a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            double upperRightLatitude, double upperRightLongitude, int maxResults,
182734901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwood            GeocoderParams params, List<Address> addrs) {
1828a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood
1829a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        if (mGeocodeProvider != null) {
1830628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood            return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
1831628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                    lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
1832628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                    maxResults, params, addrs);
18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1834a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        return null;
18359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Mock Providers
18389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void checkMockPermissionsSafe() {
18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(),
18419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1;
18429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!allowMocks) {
18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting");
18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) !=
18479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PackageManager.PERMISSION_GRANTED) {
18489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission");
1849e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        }
18509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1852e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
18536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void addTestProvider(String name, ProviderProperties properties) {
18549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1856a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
1857a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood            throw new IllegalArgumentException("Cannot mock the passive location provider");
1858a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        }
1859a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood
186086328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood        long identity = Binder.clearCallingIdentity();
18612f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            MockProvider provider = new MockProvider(name, this, properties);
18637566c1debebe072af76411e11d96810fd1409482Mike Lockwood            // remove the real provider if we are replacing GPS or network provider
18647566c1debebe072af76411e11d96810fd1409482Mike Lockwood            if (LocationManager.GPS_PROVIDER.equals(name)
18651332b53522e281012fefb34bfbcc68a03028f516Nick Pelly                    || LocationManager.NETWORK_PROVIDER.equals(name)
18661332b53522e281012fefb34bfbcc68a03028f516Nick Pelly                    || LocationManager.FUSED_PROVIDER.equals(name)) {
1867d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                LocationProviderInterface p = mProvidersByName.get(name);
1868d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                if (p != null) {
18696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    removeProviderLocked(p);
18707566c1debebe072af76411e11d96810fd1409482Mike Lockwood                }
18717566c1debebe072af76411e11d96810fd1409482Mike Lockwood            }
187215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (mProvidersByName.get(name) != null) {
18739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
18749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            addProviderLocked(provider);
18767ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mMockProviders.put(name, provider);
18776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mLastLocation.put(name, null);
18789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
18799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
188086328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood        Binder.restoreCallingIdentity(identity);
18819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1883e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeTestProvider(String provider) {
18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18862f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18877ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18887ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
189186328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            long identity = Binder.clearCallingIdentity();
18926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            removeProviderLocked(mProvidersByName.get(provider));
18937ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mMockProviders.remove(mockProvider);
18946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
18956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // reinstate real provider if available
18966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            LocationProviderInterface realProvider = mRealProviders.get(provider);
18976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (realProvider != null) {
18986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                addProviderLocked(realProvider);
18996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
19006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mLastLocation.put(provider, null);
19019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
190286328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            Binder.restoreCallingIdentity(identity);
19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1906e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
19079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderLocation(String provider, Location loc) {
19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
19092f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
19107ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
19117ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
19139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
191495427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
191595427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            long identity = Binder.clearCallingIdentity();
19167ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.setLocation(loc);
191795427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            Binder.restoreCallingIdentity(identity);
19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1921e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
19229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderLocation(String provider) {
19239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
19242f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
19257ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
19267ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
19279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19297ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.clearLocation();
19309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1933e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
19349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderEnabled(String provider, boolean enabled) {
19359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
19362f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
19377ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
19387ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
19399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
19409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
194186328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            long identity = Binder.clearCallingIdentity();
19429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (enabled) {
19437ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                mockProvider.enable();
19449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEnabledProviders.add(provider);
19459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDisabledProviders.remove(provider);
19469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
19477ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                mockProvider.disable();
19489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEnabledProviders.remove(provider);
19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDisabledProviders.add(provider);
19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
195286328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            Binder.restoreCallingIdentity(identity);
19539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1956e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
19579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderEnabled(String provider) {
19589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
19592f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
19607ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
19617ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
19629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
19639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
196486328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            long identity = Binder.clearCallingIdentity();
19659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEnabledProviders.remove(provider);
19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDisabledProviders.remove(provider);
19679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
196886328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            Binder.restoreCallingIdentity(identity);
19699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1972e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
19739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
19749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
19752f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
19767ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
19777ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
19789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
19799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19807ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.setStatus(status, extras, updateTime);
19819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1984e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
19859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderStatus(String provider) {
19869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
19872f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
19887ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
19897ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
19909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
19919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19927ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.clearStatus();
19939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void log(String log) {
19979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Log.isLoggable(TAG, Log.VERBOSE)) {
19988a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.d(TAG, log);
19999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2001e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
2002e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
20039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
20049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
20059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
20060528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            pw.println("Permission Denial: can't dump LocationManagerService from from pid="
20079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Binder.getCallingPid()
20089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", uid=" + Binder.getCallingUid());
20099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
20109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2011e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
20122f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
20139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("Current Location Manager state:");
20149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Location Listeners:");
20156fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (Receiver receiver : mReceivers.values()) {
20166fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                pw.println("    " + receiver);
20179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Records by Provider:");
20196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
20206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                pw.println("    " + entry.getKey() + ":");
20216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                for (UpdateRecord record : entry.getValue()) {
20226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    pw.println("      " + record);
20239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
20249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Last Known Locations:");
20266fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
20276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                String provider = entry.getKey();
20286fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                Location location = entry.getValue();
20296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                pw.println("    " + provider + ": " + location);
20309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2032e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly            mGeofenceManager.dump(pw);
20336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
20349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mEnabledProviders.size() > 0) {
20359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Enabled Providers:");
20369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (String i : mEnabledProviders) {
20379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i);
20389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2039e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
20409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mDisabledProviders.size() > 0) {
20429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Disabled Providers:");
20439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (String i : mDisabledProviders) {
20449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i);
20459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
20469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20474035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            pw.append("  ");
20484035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            mBlacklist.dump(pw);
20499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mMockProviders.size() > 0) {
20509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Mock Providers:");
20519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
20527ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                    i.getValue().dump(pw, "      ");
20539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
20549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
205674fa7eabda3d0c1a85e0b568e3fc4230ed4fe7a4Nick Pelly            pw.append("  fudger: ");
205774fa7eabda3d0c1a85e0b568e3fc4230ed4fe7a4Nick Pelly            mLocationFudger.dump(fd, pw,  args);
205874fa7eabda3d0c1a85e0b568e3fc4230ed4fe7a4Nick Pelly
20596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (args.length > 0 && "short".equals(args[0])) {
20606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                return;
20616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
20623c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger            for (LocationProviderInterface provider: mProviders) {
20636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                pw.print(provider.getName() + " Internal State");
20646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                if (provider instanceof LocationProviderProxy) {
20656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    LocationProviderProxy proxy = (LocationProviderProxy) provider;
20666fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    pw.print(" (" + proxy.getConnectedPackageName() + ")");
20673c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger                }
20686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                pw.println(":");
20696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                provider.dump(fd, pw, args);
20703c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger            }
20719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2074