LocationManagerService.java revision 37425c3475877f2fdadb78f669ec57fecf82dca7
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;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.content.pm.PackageManager.NameNotFoundException;
28628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwoodimport android.content.res.Resources;
29bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsuimport android.database.ContentObserver;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Address;
3103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwoodimport android.location.Criteria;
3234901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwoodimport android.location.GeocoderParams;
336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.location.Geofence;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.IGpsStatusListener;
3515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwoodimport android.location.IGpsStatusProvider;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.ILocationListener;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.ILocationManager;
3822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport android.location.INetInitiatedListener;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Location;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationManager;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationProvider;
426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.location.LocationRequest;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
473d12b51ee38537f6760a833618948f936e75561dMike Lockwoodimport android.os.Looper;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager;
50e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwoodimport android.os.Process;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.os.SystemClock;
535ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackbornimport android.os.UserHandle;
547e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackbornimport android.os.WorkSource;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
578a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
59e97ae40dffe7d7f8917c51c4f3f6c1b18c238565Mike Lockwoodimport com.android.internal.content.PackageMonitor;
606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport com.android.internal.location.ProviderProperties;
616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport com.android.internal.location.ProviderRequest;
6243e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport com.android.server.location.GeocoderProxy;
63e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pellyimport com.android.server.location.GeofenceManager;
6443e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport com.android.server.location.GpsLocationProvider;
654035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pellyimport com.android.server.location.LocationBlacklist;
6674fa7eabda3d0c1a85e0b568e3fc4230ed4fe7a4Nick Pellyimport com.android.server.location.LocationFudger;
6743e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport com.android.server.location.LocationProviderInterface;
6843e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport com.android.server.location.LocationProviderProxy;
6943e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport com.android.server.location.MockProvider;
7043e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport com.android.server.location.PassiveProvider;
7143e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwood
7243e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.io.FileDescriptor;
7343e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.io.PrintWriter;
7443e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.util.ArrayList;
756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport java.util.Arrays;
7643e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.util.HashMap;
7743e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.util.HashSet;
7843e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.util.List;
7943e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.util.Map;
8043e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.util.Set;
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The service class that manages LocationProviders and issues location
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * updates and alerts.
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
86bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsupublic class LocationManagerService extends ILocationManager.Stub implements Runnable {
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "LocationManagerService";
886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public static final boolean D = false;
896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final String WAKELOCK_KEY = TAG;
916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final String THREAD_NAME = TAG;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    // Location resolution level: no location data whatsoever
9437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private static final int RESOLUTION_LEVEL_NONE = 0;
9537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    // Location resolution level: coarse location data only
9637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private static final int RESOLUTION_LEVEL_COARSE = 1;
9737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    // Location resolution level: fine location data
9837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private static final int RESOLUTION_LEVEL_FINE = 2;
9937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_MOCK_LOCATION =
1016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            android.Manifest.permission.ACCESS_MOCK_LOCATION;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
1036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
104275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood    private static final String INSTALL_LOCATION_PROVIDER =
1056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
1066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final String NETWORK_LOCATION_SERVICE_ACTION =
1086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            "com.android.location.service.v2.NetworkLocationProvider";
1096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final String FUSED_LOCATION_SERVICE_ACTION =
1106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            "com.android.location.service.FusedLocationProvider";
1116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final int MSG_LOCATION_CHANGED = 1;
1136fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
114f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly    // Location Providers may sometimes deliver location updates
115f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly    // slightly faster that requested - provide grace period so
116f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly    // we don't unnecessarily filter events that are otherwise on
117f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly    // time
1186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
119f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly
1206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final Context mContext;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // used internally for synchronization
1256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final Object mLock = new Object();
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // --- fields below are final after init() ---
12874fa7eabda3d0c1a85e0b568e3fc4230ed4fe7a4Nick Pelly    private LocationFudger mLocationFudger;
1296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private GeofenceManager mGeofenceManager;
1306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private PowerManager.WakeLock mWakeLock;
1316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private PackageManager mPackageManager;
132628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood    private GeocoderProxy mGeocodeProvider;
13315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private IGpsStatusProvider mGpsStatusProvider;
13422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private INetInitiatedListener mNetInitiatedListener;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private LocationWorkerHandler mLocationHandler;
1364035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    private PassiveProvider mPassiveProvider;  // track passive provider for special cases
1374035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    private LocationBlacklist mBlacklist;
1386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // --- fields below are protected by mWakeLock ---
1406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private int mPendingBroadcasts;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // --- fields below are protected by mLock ---
1436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // Set of providers that are explicitly enabled
1446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final Set<String> mEnabledProviders = new HashSet<String>();
1457566c1debebe072af76411e11d96810fd1409482Mike Lockwood
1466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // Set of providers that are explicitly disabled
1476fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final Set<String> mDisabledProviders = new HashSet<String>();
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // Mock (test) providers
1506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final HashMap<String, MockProvider> mMockProviders =
1516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            new HashMap<String, MockProvider>();
152e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
1536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // all receivers
1542f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final HashMap<Object, Receiver> mReceivers = new HashMap<Object, Receiver>();
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // currently installed providers (with mocks replacing real providers)
157d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    private final ArrayList<LocationProviderInterface> mProviders =
1586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            new ArrayList<LocationProviderInterface>();
15915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
1606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // real providers, saved here when mocked out
1616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final HashMap<String, LocationProviderInterface> mRealProviders =
1626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            new HashMap<String, LocationProviderInterface>();
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // mapping from provider name to provider
1656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final HashMap<String, LocationProviderInterface> mProvidersByName =
1666fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            new HashMap<String, LocationProviderInterface>();
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // mapping from provider name to all its UpdateRecords
1696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
1706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            new HashMap<String, ArrayList<UpdateRecord>>();
1716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // mapping from provider name to last known location
1736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final HashMap<String, Location> mLastLocation = new HashMap<String, Location>();
1747e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn
1756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // all providers that operate over proxy, for authorizing incoming location
1766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final ArrayList<LocationProviderProxy> mProxyProviders =
1776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            new ArrayList<LocationProviderProxy>();
1786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
17938389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease    // current active user on the device - other users are denied location data
18038389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease    private int mCurrentUserId = UserHandle.USER_OWNER;
18138389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease
1826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public LocationManagerService(Context context) {
1836fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        super();
1846fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mContext = context;
1856fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1866fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "Constructed");
1876fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // most startup is deferred until systemReady()
1896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
1906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void systemReady() {
1926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Thread thread = new Thread(null, this, THREAD_NAME);
1936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        thread.start();
1946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
1956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
1976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void run() {
1986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
1996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Looper.prepare();
2006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mLocationHandler = new LocationWorkerHandler();
2016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        init();
2026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Looper.loop();
2036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
2046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void init() {
2066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "init()");
2076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
2096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
2106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mPackageManager = mContext.getPackageManager();
2116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
212bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu        mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
213bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu        mBlacklist.init();
214df9ec6171f6b7f3075d7f8174e9ae6ecf080c917Victoria Lease        mLocationFudger = new LocationFudger(mContext, mLocationHandler);
215bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu
2166fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        synchronized (mLock) {
2176fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            loadProvidersLocked();
2186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
219bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu
2204035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
2216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // listen for settings changes
223bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu        mContext.getContentResolver().registerContentObserver(
224bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu                Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
225bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu                new ContentObserver(mLocationHandler) {
226bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu           @Override
227bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu            public void onChange(boolean selfChange) {
228bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu               synchronized (mLock) {
229bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu                   updateProvidersLocked();
230bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu               }
231bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu            }
232b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        }, UserHandle.USER_ALL);
2336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mPackageMonitor.register(mContext, Looper.myLooper(), true);
234bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu
23538389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        // listen for user change
23638389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        IntentFilter intentFilter = new IntentFilter();
23738389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
23838389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease
23938389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        mContext.registerReceiverAsUser(new BroadcastReceiver() {
24038389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease            @Override
24138389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease            public void onReceive(Context context, Intent intent) {
24238389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease                String action = intent.getAction();
24338389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease                if (Intent.ACTION_USER_SWITCHED.equals(action)) {
24438389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease                    switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
24538389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease                }
24638389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease            }
24738389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        }, UserHandle.ALL, intentFilter, null, null);
24838389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease
249bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu        updateProvidersLocked();
2506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
2516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void loadProvidersLocked() {
2535c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        // create a passive location provider, which is always enabled
2545c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        PassiveProvider passiveProvider = new PassiveProvider(this);
2555c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        addProviderLocked(passiveProvider);
2565c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        mEnabledProviders.add(passiveProvider.getName());
2575c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        mPassiveProvider = passiveProvider;
2585c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease
2596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (GpsLocationProvider.isSupported()) {
2606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // Create a gps location provider
2616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);
2626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
2636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
2646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            addProviderLocked(gpsProvider);
2656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mRealProviders.put(LocationManager.GPS_PROVIDER, gpsProvider);
2666fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        /*
2696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Load package name(s) containing location provider support.
2706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        These packages can contain services implementing location providers:
2716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Geocoder Provider, Network Location Provider, and
2726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Fused Location Provider. They will each be searched for
2736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        service components implementing these providers.
2746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        The location framework also has support for installation
2756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        of new location providers at run-time. The new package does not
2766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        have to be explicitly listed here, however it must have a signature
2776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        that matches the signature of at least one package on this list.
2786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        */
2796fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Resources resources = mContext.getResources();
2806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        ArrayList<String> providerPackageNames = new ArrayList<String>();
2816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        String[] pkgs1 = resources.getStringArray(
2826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                com.android.internal.R.array.config_locationProviderPackageNames);
2836fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        String[] pkgs2 = resources.getStringArray(
2846fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                com.android.internal.R.array.config_overlay_locationProviderPackageNames);
2856fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "built-in location providers: " + Arrays.toString(pkgs1));
2866fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "overlay location providers: " + Arrays.toString(pkgs2));
2876fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (pkgs1 != null) providerPackageNames.addAll(Arrays.asList(pkgs1));
2886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (pkgs2 != null) providerPackageNames.addAll(Arrays.asList(pkgs2));
2896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // bind to network provider
2916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
2926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                mContext,
2936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                LocationManager.NETWORK_PROVIDER,
2946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                NETWORK_LOCATION_SERVICE_ACTION,
295b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                providerPackageNames, mLocationHandler, mCurrentUserId);
2966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (networkProvider != null) {
2976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
2986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mProxyProviders.add(networkProvider);
2996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            addProviderLocked(networkProvider);
3006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else {
3016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            Slog.w(TAG,  "no network location provider found");
3026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
3036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
3046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // bind to fused provider
3056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(
3066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                mContext,
3076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                LocationManager.FUSED_PROVIDER,
3086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                FUSED_LOCATION_SERVICE_ACTION,
309b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                providerPackageNames, mLocationHandler, mCurrentUserId);
3106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (fusedLocationProvider != null) {
3116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            addProviderLocked(fusedLocationProvider);
3126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mProxyProviders.add(fusedLocationProvider);
3136fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mEnabledProviders.add(fusedLocationProvider.getName());
314c3575188c2f2ad27b1f03b9b9c0705a686a5e42fKenny Root            mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
3156fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else {
3166fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            Slog.e(TAG, "no fused location provider found",
3176fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    new IllegalStateException("Location service needs a fused location provider"));
3186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // bind to geocoder provider
321b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        mGeocodeProvider = GeocoderProxy.createAndBind(mContext, providerPackageNames,
322b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                mCurrentUserId);
3236fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (mGeocodeProvider == null) {
3246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            Slog.e(TAG,  "no geocoder provider found");
3256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
3266fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
3279637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
32938389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease     * Called when the device's active user changes.
33038389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease     * @param userId the new active user's UserId
33138389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease     */
33238389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease    private void switchUser(int userId) {
33383762d22c9bde92d412cf5a263a228d705606721Victoria Lease        mBlacklist.switchUser(userId);
33438389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        synchronized (mLock) {
335b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            mLastLocation.clear();
336b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            for (LocationProviderInterface p : mProviders) {
337b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                updateProviderListenersLocked(p.getName(), false, mCurrentUserId);
338b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                p.switchUser(userId);
339b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            }
34038389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease            mCurrentUserId = userId;
341b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            updateProvidersLocked();
34238389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        }
34338389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease    }
34438389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease
34538389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease    /**
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A wrapper class holding either an ILocationListener or a PendingIntent to receive
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * location updates.
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
34948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
3506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final int mUid;  // uid of receiver
3516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final int mPid;  // pid of receiver
3526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final String mPackageName;  // package name of receiver
35337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        final int mAllowedResolutionLevel;  // resolution level allowed to receiver
3546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ILocationListener mListener;
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final PendingIntent mPendingIntent;
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Object mKey;
3586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
3592f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
360f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly
36148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        int mPendingBroadcasts;
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
3646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                String packageName) {
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = listener;
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPendingIntent = intent;
3676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (listener != null) {
3686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                mKey = listener.asBinder();
3696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            } else {
3706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                mKey = intent;
3716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
37237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
3736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mUid = uid;
3746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mPid = pid;
3756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mPackageName = packageName;
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean equals(Object otherObj) {
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (otherObj instanceof Receiver) {
3816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                return mKey.equals(((Receiver)otherObj).mKey);
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int hashCode() {
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mKey.hashCode();
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3903681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
3936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            StringBuilder s = new StringBuilder();
3946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append("Reciever[");
3956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append(Integer.toHexString(System.identityHashCode(this)));
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
3976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                s.append(" listener");
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                s.append(" intent");
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (String p : mUpdateRecords.keySet()) {
4026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                s.append(" ").append(mUpdateRecords.get(p).toString());
4036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
4046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append("]");
4056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return s.toString();
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean isListener() {
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mListener != null;
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean isPendingIntent() {
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mPendingIntent != null;
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ILocationListener getListener() {
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mListener;
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("Request for non-existent listener");
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
42648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
42748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
42848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
42948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mListener.onStatusChanged(provider, status, extras);
430e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        // call this after broadcasting so we do not increment
431e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        // if we throw an exeption.
432e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        incrementPendingBroadcastsLocked();
43348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent statusChanged = new Intent();
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                statusChanged.putExtras(extras);
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
44248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
44348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
44448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
4456c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn                        mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
44637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                                getResolutionPermission(mAllowedResolutionLevel));
44748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
44848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
44948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
45048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (PendingIntent.CanceledException e) {
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean callLocationChangedLocked(Location location) {
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
46148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
46248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
46348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
46448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mListener.onLocationChanged(location);
465e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        // call this after broadcasting so we do not increment
466e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        // if we throw an exeption.
467e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        incrementPendingBroadcastsLocked();
46848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent locationChanged = new Intent();
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, location);
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
47648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
47748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
47848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
4796c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn                        mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
48037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                                getResolutionPermission(mAllowedResolutionLevel));
48148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
48248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
48348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
48448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
48548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                } catch (PendingIntent.CanceledException e) {
48648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    return false;
48748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
48848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
48948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            return true;
49048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
49148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
49248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        public boolean callProviderEnabledLocked(String provider, boolean enabled) {
49348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (mListener != null) {
49448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                try {
49548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
49648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
49748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
49848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (enabled) {
49948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            mListener.onProviderEnabled(provider);
50048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        } else {
50148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            mListener.onProviderDisabled(provider);
50248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
503e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        // call this after broadcasting so we do not increment
504e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        // if we throw an exeption.
505e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        incrementPendingBroadcastsLocked();
50648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
50748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                } catch (RemoteException e) {
50848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    return false;
50948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
51048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            } else {
51148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                Intent providerIntent = new Intent();
51248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
51348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                try {
51448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
51548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
51648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
5176c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn                        mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
51837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                                getResolutionPermission(mAllowedResolutionLevel));
51948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
52048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
52148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
52248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (PendingIntent.CanceledException e) {
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
530f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly        @Override
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
5326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (D) Log.d(TAG, "Location listener died");
5336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
5342f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeUpdatesLocked(this);
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
53748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            synchronized (this) {
53848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                if (mPendingBroadcasts > 0) {
53948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    LocationManagerService.this.decrementPendingBroadcasts();
54048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    mPendingBroadcasts = 0;
54148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
54248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
54348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
54448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
545e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        @Override
54648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        public void onSendFinished(PendingIntent pendingIntent, Intent intent,
54748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                int resultCode, String resultData, Bundle resultExtras) {
5480528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            synchronized (this) {
5490528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                decrementPendingBroadcastsLocked();
5500528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
55148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
55248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
5530528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // this must be called while synchronized by caller in a synchronized block
55448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        // containing the sending of the broadcaset
55548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        private void incrementPendingBroadcastsLocked() {
55648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (mPendingBroadcasts++ == 0) {
5570528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                LocationManagerService.this.incrementPendingBroadcasts();
55848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
55948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
56048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
5610528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        private void decrementPendingBroadcastsLocked() {
5620528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (--mPendingBroadcasts == 0) {
5630528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                LocationManagerService.this.decrementPendingBroadcasts();
56448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
56548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
56648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
56748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
568e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
56948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    public void locationCallbackFinished(ILocationListener listener) {
570080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //Do not use getReceiver here as that will add the ILocationListener to
571080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //the receiver list if it is not found.  If it is not found then the
572080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //LocationListener was removed when it had a pending broadcast and should
573080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //not be added back.
574080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        IBinder binder = listener.asBinder();
575080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        Receiver receiver = mReceivers.get(binder);
57648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        if (receiver != null) {
5770528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            synchronized (receiver) {
5780528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                // so wakelock calls will succeed
5790528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                long identity = Binder.clearCallingIdentity();
5800528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                receiver.decrementPendingBroadcastsLocked();
5810528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                Binder.restoreCallingIdentity(identity);
5820528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood           }
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5866fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void addProviderLocked(LocationProviderInterface provider) {
58715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProviders.add(provider);
58815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProvidersByName.put(provider.getName(), provider);
58915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
59015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
5916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void removeProviderLocked(LocationProviderInterface provider) {
5926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        provider.disable();
59315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProviders.remove(provider);
59415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProvidersByName.remove(provider.getName());
59515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
59615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
5973d12b51ee38537f6760a833618948f936e75561dMike Lockwood
598b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease    private boolean isAllowedBySettingsLocked(String provider, int userId) {
599b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        if (userId != mCurrentUserId) {
600b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            return false;
601b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        }
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabledProviders.contains(provider)) {
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDisabledProviders.contains(provider)) {
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Use system settings
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ContentResolver resolver = mContext.getContentResolver();
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
611b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId);
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    /**
61537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Returns the permission string associated with the specified resolution level.
61637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
61737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param resolutionLevel the resolution level
61837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @return the permission string
6196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     */
62037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private String getResolutionPermission(int resolutionLevel) {
62137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        switch (resolutionLevel) {
62237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            case RESOLUTION_LEVEL_FINE:
62337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                return android.Manifest.permission.ACCESS_FINE_LOCATION;
62437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            case RESOLUTION_LEVEL_COARSE:
62537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                return android.Manifest.permission.ACCESS_COARSE_LOCATION;
62637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            default:
62737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                return null;
6286c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn        }
629da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease    }
6306c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn
631da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease    /**
63237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Returns the resolution level allowed to the given PID/UID pair.
63337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
63437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param pid the PID
63537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param uid the UID
63637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @return resolution level allowed to the pid/uid pair
637da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease     */
63837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private int getAllowedResolutionLevel(int pid, int uid) {
63937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
64037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                pid, uid) == PackageManager.PERMISSION_GRANTED) {
64137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            return RESOLUTION_LEVEL_FINE;
64237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
64337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                pid, uid) == PackageManager.PERMISSION_GRANTED) {
64437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            return RESOLUTION_LEVEL_COARSE;
64537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        } else {
64637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            return RESOLUTION_LEVEL_NONE;
647da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease        }
6484fab68b5324e1f9b6765cdc33e66d1f074623dc2Victoria Lease    }
6494fab68b5324e1f9b6765cdc33e66d1f074623dc2Victoria Lease
6504fab68b5324e1f9b6765cdc33e66d1f074623dc2Victoria Lease    /**
65137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Returns the resolution level allowed to the caller
65237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
65337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @return resolution level allowed to caller
65437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     */
65537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private int getCallerAllowedResolutionLevel() {
65637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
65737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    }
65837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease
65937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    /**
66037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Throw SecurityException if specified resolution level is insufficient to use geofences.
66137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
66237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param allowedResolutionLevel resolution level allowed to caller
6634fab68b5324e1f9b6765cdc33e66d1f074623dc2Victoria Lease     */
66437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
66537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
6664fab68b5324e1f9b6765cdc33e66d1f074623dc2Victoria Lease            throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
6674fab68b5324e1f9b6765cdc33e66d1f074623dc2Victoria Lease        }
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
67037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    /**
67137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Return the minimum resolution level required to use the specified location provider.
67237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
67337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param provider the name of the location provider
67437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @return minimum resolution level required for provider
67537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     */
67637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private int getMinimumResolutionLevelForProviderUse(String provider) {
6778dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease        if (LocationManager.GPS_PROVIDER.equals(provider) ||
6788dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease                LocationManager.PASSIVE_PROVIDER.equals(provider)) {
6798dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease            // gps and passive providers require FINE permission
68037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            return RESOLUTION_LEVEL_FINE;
6818dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease        } else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
6828dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease                LocationManager.FUSED_PROVIDER.equals(provider)) {
6838dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease            // network and fused providers are ok with COARSE or FINE
68437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            return RESOLUTION_LEVEL_COARSE;
685941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu        } else {
686941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu            // mock providers
687941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu            LocationProviderInterface lp = mMockProviders.get(provider);
688941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu            if (lp != null) {
689941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                ProviderProperties properties = lp.getProperties();
690941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                if (properties != null) {
691941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                    if (properties.mRequiresSatellite) {
692941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                        // provider requiring satellites require FINE permission
69337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                        return RESOLUTION_LEVEL_FINE;
694941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                    } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
695941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                        // provider requiring network and or cell require COARSE or FINE
69637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                        return RESOLUTION_LEVEL_COARSE;
697941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                    }
698941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                }
699941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu            }
7008dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease        }
70137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
702da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease    }
703da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease
70437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    /**
70537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Throw SecurityException if specified resolution level is insufficient to use the named
70637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * location provider.
70737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
70837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param allowedResolutionLevel resolution level allowed to caller
70937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param providerName the name of the location provider
71037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     */
71137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
71237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            String providerName) {
71337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
71437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        if (allowedResolutionLevel < requiredResolutionLevel) {
71537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            switch (requiredResolutionLevel) {
71637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                case RESOLUTION_LEVEL_FINE:
71737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    throw new SecurityException("\"" + providerName + "\" location provider " +
71837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                            "requires ACCESS_FINE_LOCATION permission.");
71937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                case RESOLUTION_LEVEL_COARSE:
72037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    throw new SecurityException("\"" + providerName + "\" location provider " +
72137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                            "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
72237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                default:
72337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    throw new SecurityException("Insufficient permission for \"" + providerName +
72437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                            "\" location provider.");
725da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease            }
726da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease        }
7278dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease    }
7288dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease
7296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    /**
7306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * Returns all providers by name, including passive, but excluding
7310d21e2161f8542db0a54bf80b74b7fd33afef6f6Laurent Tu     * fused, also including ones that are not permitted to
7320d21e2161f8542db0a54bf80b74b7fd33afef6f6Laurent Tu     * be accessed by the calling activity or are currently disabled.
7336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     */
734e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<String> getAllProviders() {
7366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        ArrayList<String> out;
7376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        synchronized (mLock) {
7386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            out = new ArrayList<String>(mProviders.size());
7396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (LocationProviderInterface provider : mProviders) {
7406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                String name = provider.getName();
7416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                if (LocationManager.FUSED_PROVIDER.equals(name)) {
7426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    continue;
7436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                }
7446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                out.add(name);
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7486fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "getAllProviders()=" + out);
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return out;
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    /**
7536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * Return all providers by name, that match criteria and are optionally
7546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * enabled.
7556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * Can return passive provider, but never returns fused provider.
7566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     */
757e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
75803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
75937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
7606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        ArrayList<String> out;
761b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        int callingUserId = UserHandle.getCallingUserId();
762b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        long identity = Binder.clearCallingIdentity();
763b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        try {
764b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            synchronized (mLock) {
765b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                out = new ArrayList<String>(mProviders.size());
766b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                for (LocationProviderInterface provider : mProviders) {
767b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    String name = provider.getName();
768b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    if (LocationManager.FUSED_PROVIDER.equals(name)) {
7698dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease                        continue;
7708dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease                    }
77137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
772b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        if (enabledOnly && !isAllowedBySettingsLocked(name, callingUserId)) {
773b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                            continue;
774b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        }
775b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        if (criteria != null && !LocationProvider.propertiesMeetCriteria(
776b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                                name, provider.getProperties(), criteria)) {
777b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                            continue;
778b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        }
779b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        out.add(name);
7808dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease                    }
78103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                }
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
783b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        } finally {
784b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            Binder.restoreCallingIdentity(identity);
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
78603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
7876fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "getProviders()=" + out);
7886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        return out;
78903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
79003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
79103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    /**
7926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * Return the name of the best provider given a Criteria object.
7936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * This method has been deprecated from the public API,
7948dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease     * and the whole LocationProvider (including #meetsCriteria)
7956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * has been deprecated as well. So this method now uses
7966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * some simplified logic.
79703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood     */
798e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
79903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public String getBestProvider(Criteria criteria, boolean enabledOnly) {
8006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        String result = null;
80103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
8026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        List<String> providers = getProviders(criteria, enabledOnly);
8038dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease        if (!providers.isEmpty()) {
8046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            result = pickBest(providers);
8056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
8066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return result;
80703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
8086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        providers = getProviders(null, enabledOnly);
8098dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease        if (!providers.isEmpty()) {
8106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            result = pickBest(providers);
8116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
8126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return result;
81303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
81403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
8156fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
8166fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        return null;
8176fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
81803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
8196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private String pickBest(List<String> providers) {
8201925e290e7ac2801311cb4e732d1bc5a5f3e0c44Victoria Lease        if (providers.contains(LocationManager.GPS_PROVIDER)) {
8216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return LocationManager.GPS_PROVIDER;
8221925e290e7ac2801311cb4e732d1bc5a5f3e0c44Victoria Lease        } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
8231925e290e7ac2801311cb4e732d1bc5a5f3e0c44Victoria Lease            return LocationManager.NETWORK_PROVIDER;
8246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else {
8256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return providers.get(0);
82603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
82703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
82803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
829e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
83003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public boolean providerMeetsCriteria(String provider, Criteria criteria) {
83103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
83203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        if (p == null) {
83303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            throw new IllegalArgumentException("provider=" + provider);
83403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
8356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
8366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        boolean result = LocationProvider.propertiesMeetCriteria(
8376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                p.getName(), p.getProperties(), criteria);
8386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result);
8396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        return result;
84003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
84103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateProvidersLocked() {
8430c5a04014d3833c9a82772a832d3bc6410fc52acBrad Fitzpatrick        boolean changesMade = false;
84415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        for (int i = mProviders.size() - 1; i >= 0; i--) {
845d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            LocationProviderInterface p = mProviders.get(i);
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean isEnabled = p.isEnabled();
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = p.getName();
848b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            boolean shouldBeEnabled = isAllowedBySettingsLocked(name, mCurrentUserId);
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isEnabled && !shouldBeEnabled) {
850b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                updateProviderListenersLocked(name, false, mCurrentUserId);
8510c5a04014d3833c9a82772a832d3bc6410fc52acBrad Fitzpatrick                changesMade = true;
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (!isEnabled && shouldBeEnabled) {
853b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                updateProviderListenersLocked(name, true, mCurrentUserId);
8540c5a04014d3833c9a82772a832d3bc6410fc52acBrad Fitzpatrick                changesMade = true;
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8560c5a04014d3833c9a82772a832d3bc6410fc52acBrad Fitzpatrick        }
8570c5a04014d3833c9a82772a832d3bc6410fc52acBrad Fitzpatrick        if (changesMade) {
8585ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn            mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
8595ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn                    UserHandle.ALL);
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
863b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease    private void updateProviderListenersLocked(String provider, boolean enabled, int userId) {
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int listeners = 0;
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
866d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
8676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (p == null) return;
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<Receiver> deadReceivers = null;
870e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (records != null) {
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int N = records.size();
8746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (int i = 0; i < N; i++) {
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                UpdateRecord record = records.get(i);
876b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (UserHandle.getUserId(record.mReceiver.mUid) == userId) {
877b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    // Sends a notification message to the receiver
878b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
879b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        if (deadReceivers == null) {
880b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                            deadReceivers = new ArrayList<Receiver>();
881b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        }
882b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        deadReceivers.add(record.mReceiver);
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
884b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    listeners++;
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (deadReceivers != null) {
8906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (int i = deadReceivers.size() - 1; i >= 0; i--) {
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeUpdatesLocked(deadReceivers.get(i));
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
894e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (enabled) {
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.enable();
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (listeners > 0) {
8986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                applyRequirementsLocked(provider);
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.disable();
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void applyRequirementsLocked(String provider) {
9066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        LocationProviderInterface p = mProvidersByName.get(provider);
9076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (p == null) return;
9086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
9106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        WorkSource worksource = new WorkSource();
9116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        ProviderRequest providerRequest = new ProviderRequest();
9126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (records != null) {
9146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (UpdateRecord record : records) {
915b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
916b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    LocationRequest locationRequest = record.mRequest;
917b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    providerRequest.locationRequests.add(locationRequest);
918b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    if (locationRequest.getInterval() < providerRequest.interval) {
919b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        providerRequest.reportLocation = true;
920b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        providerRequest.interval = locationRequest.getInterval();
921b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    }
9227e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn                }
9237e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            }
9246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
9256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (providerRequest.reportLocation) {
9266fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // calculate who to blame for power
9276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // This is somewhat arbitrary. We pick a threshold interval
9286fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // that is slightly higher that the minimum interval, and
9296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // spread the blame across all applications with a request
9306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // under that threshold.
9316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
9326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                for (UpdateRecord record : records) {
933b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
934b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        LocationRequest locationRequest = record.mRequest;
935b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        if (locationRequest.getInterval() <= thresholdInterval) {
936b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                            worksource.add(record.mReceiver.mUid);
937b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        }
9386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    }
9397e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn                }
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
9436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
9446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        p.setRequest(providerRequest, worksource);
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class UpdateRecord {
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String mProvider;
9496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final LocationRequest mRequest;
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Receiver mReceiver;
9512f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Location mLastFixBroadcast;
9522f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        long mLastStatusBroadcast;
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Note: must be constructed with lock held.
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
9576fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProvider = provider;
9596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mRequest = request;
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mReceiver = receiver;
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (records == null) {
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                records = new ArrayList<UpdateRecord>();
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRecordsByProvider.put(provider, records);
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!records.contains(this)) {
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                records.add(this);
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Method to be called when a record will no longer be used.  Calling this multiple times
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * must have the same effect as calling it once.
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
9766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        void disposeLocked(boolean removeReceiver) {
9776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // remove from mRecordsByProvider
9786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
9796fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (globalRecords != null) {
9806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                globalRecords.remove(this);
9816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
9826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
9836fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (!removeReceiver) return;  // the caller will handle the rest
9846fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
9856fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // remove from Receiver#mUpdateRecords
9866fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
9876fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (receiverRecords != null) {
9886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                receiverRecords.remove(this.mProvider);
9896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
9906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // and also remove the Receiver if it has no more update records
9916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                if (removeReceiver && receiverRecords.size() == 0) {
9926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    removeUpdatesLocked(mReceiver);
9936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                }
9943a76fd627945c1df59aa0318867401e0e53da022Mike Lockwood            }
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
9996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            StringBuilder s = new StringBuilder();
10006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append("UpdateRecord[");
10016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append(mProvider);
10026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append(' ').append(mReceiver.mPackageName).append('(');
10036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append(mReceiver.mUid).append(')');
10046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append(' ').append(mRequest);
10056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append(']');
10066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return s.toString();
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private Receiver getReceiver(ILocationListener listener, int pid, int uid, String packageName) {
10112f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        IBinder binder = listener.asBinder();
10122f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver receiver = mReceivers.get(binder);
10132f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (receiver == null) {
10146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            receiver = new Receiver(listener, null, pid, uid, packageName);
10152f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            mReceivers.put(binder, receiver);
10162f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
10172f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            try {
10186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                receiver.getListener().asBinder().linkToDeath(receiver, 0);
10192f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            } catch (RemoteException e) {
10208a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.e(TAG, "linkToDeath failed:", e);
10212f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                return null;
10222f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
10232f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
10242f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        return receiver;
10252f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
10262f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
10276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private Receiver getReceiver(PendingIntent intent, int pid, int uid, String packageName) {
10282f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver receiver = mReceivers.get(intent);
10292f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (receiver == null) {
10306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            receiver = new Receiver(null, intent, pid, uid, packageName);
10312f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            mReceivers.put(intent, receiver);
10322f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
10332f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        return receiver;
10342f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
10352f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
103637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    /**
103737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
103837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * and consistency requirements.
103937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
104037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param request the LocationRequest from which to create a sanitized version
104137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param shouldBeCoarse whether the sanitized version should be held to coarse resolution
104237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * constraints
104337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param fastestCoarseIntervalMS minimum interval allowed for coarse resolution
104437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @return a version of request that meets the given resolution and consistency requirements
104537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @hide
104637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     */
104737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel) {
104837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        LocationRequest sanitizedRequest = new LocationRequest(request);
104937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
105037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            switch (sanitizedRequest.getQuality()) {
105109016ab4dd056a16809419d612cb865a14980880Victoria Lease                case LocationRequest.ACCURACY_FINE:
105237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
105309016ab4dd056a16809419d612cb865a14980880Victoria Lease                    break;
105409016ab4dd056a16809419d612cb865a14980880Victoria Lease                case LocationRequest.POWER_HIGH:
105537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
105609016ab4dd056a16809419d612cb865a14980880Victoria Lease                    break;
105709016ab4dd056a16809419d612cb865a14980880Victoria Lease            }
105809016ab4dd056a16809419d612cb865a14980880Victoria Lease            // throttle
105937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
106037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
106109016ab4dd056a16809419d612cb865a14980880Victoria Lease            }
106237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
106337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
106409016ab4dd056a16809419d612cb865a14980880Victoria Lease            }
106574fa7eabda3d0c1a85e0b568e3fc4230ed4fe7a4Nick Pelly        }
10664e31c4fffbc42b4c2b5dca6431cfeef9e078f5b4Nick Pelly        // make getFastestInterval() the minimum of interval and fastest interval
106737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
10684e31c4fffbc42b4c2b5dca6431cfeef9e078f5b4Nick Pelly            request.setFastestInterval(request.getInterval());
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
107037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        return sanitizedRequest;
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void checkPackageName(String packageName) {
1074e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        if (packageName == null) {
10756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            throw new SecurityException("invalid package name: " + packageName);
1076e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        }
10776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        int uid = Binder.getCallingUid();
1078e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        String[] packages = mPackageManager.getPackagesForUid(uid);
1079e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        if (packages == null) {
1080e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly            throw new SecurityException("invalid UID " + uid);
1081e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        }
1082e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        for (String pkg : packages) {
1083e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly            if (packageName.equals(pkg)) return;
1084e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        }
10856fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        throw new SecurityException("invalid package name: " + packageName);
1086e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    }
1087e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
10886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void checkPendingIntent(PendingIntent intent) {
10896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (intent == null) {
10906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            throw new IllegalArgumentException("invalid pending intent: " + intent);
10916c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn        }
10926c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn    }
10936c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn
10946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private Receiver checkListenerOrIntent(ILocationListener listener, PendingIntent intent,
10956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            int pid, int uid, String packageName) {
10966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (intent == null && listener == null) {
10976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            throw new IllegalArgumentException("need eiter listener or intent");
10986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else if (intent != null && listener != null) {
10996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            throw new IllegalArgumentException("cannot register both listener and intent");
11006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else if (intent != null) {
11016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            checkPendingIntent(intent);
11026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return getReceiver(intent, pid, uid, packageName);
11036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else {
11046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return getReceiver(listener, pid, uid, packageName);
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
11096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
11106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            PendingIntent intent, String packageName) {
11116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (request == null) request = DEFAULT_LOCATION_REQUEST;
11126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkPackageName(packageName);
111337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
111437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
111537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                request.getProvider());
111637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final int pid = Binder.getCallingPid();
11196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final int uid = Binder.getCallingUid();
11206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Receiver recevier = checkListenerOrIntent(listener, intent, pid, uid, packageName);
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11222b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        // providers may use public location API's, need to clear identity
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identity = Binder.clearCallingIdentity();
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
11256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            synchronized (mLock) {
112637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
11272d4d1bf14b531de9d4238b1e41b53c77f8976405Mike Lockwood            }
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(identity);
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
11346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            int pid, int uid, String packageName) {
11356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // Figure out the provider. Either its explicitly request (legacy use cases), or
11366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // use the fused provider
11376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (request == null) request = DEFAULT_LOCATION_REQUEST;
11386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        String name = request.getProvider();
113909016ab4dd056a16809419d612cb865a14980880Victoria Lease        if (name == null) {
114009016ab4dd056a16809419d612cb865a14980880Victoria Lease            throw new IllegalArgumentException("provider name must not be null");
114109016ab4dd056a16809419d612cb865a14980880Victoria Lease        }
11426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        LocationProviderInterface provider = mProvidersByName.get(name);
11436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (provider == null) {
11446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            throw new IllegalArgumentException("provider doesn't exisit: " + provider);
11456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
11466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
11476fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Log.i(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver)) + " " +
11486fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                name + " " + request + " from " + packageName + "(" + uid + ")");
11496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
11506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        UpdateRecord record = new UpdateRecord(name, request, receiver);
11516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
11526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (oldRecord != null) {
11536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            oldRecord.disposeLocked(false);
11546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
11556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1156b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        boolean isProviderEnabled = isAllowedBySettingsLocked(name, UserHandle.getUserId(uid));
11576fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (isProviderEnabled) {
11586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            applyRequirementsLocked(name);
11596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else {
11606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // Notify the listener that updates are currently disabled
11616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            receiver.callProviderEnabledLocked(name, false);
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1165e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
11666fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void removeUpdates(ILocationListener listener, PendingIntent intent,
11676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            String packageName) {
11686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkPackageName(packageName);
116937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease
11706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final int pid = Binder.getCallingPid();
11716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final int uid = Binder.getCallingUid();
11726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Receiver receiver = checkListenerOrIntent(listener, intent, pid, uid, packageName);
11736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
11742b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        // providers may use public location API's, need to clear identity
11756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        long identity = Binder.clearCallingIdentity();
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
11772f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
11786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                removeUpdatesLocked(receiver);
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } finally {
11816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            Binder.restoreCallingIdentity(identity);
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void removeUpdatesLocked(Receiver receiver) {
11866fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
11896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
11906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            synchronized (receiver) {
11916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                if (receiver.mPendingBroadcasts > 0) {
11926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    decrementPendingBroadcasts();
11936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    receiver.mPendingBroadcasts = 0;
1194080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel                }
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // Record which providers were associated with this listener
11996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        HashSet<String> providers = new HashSet<String>();
12006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
12016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (oldRecords != null) {
12026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // Call dispose() on the obsolete update records.
12036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (UpdateRecord record : oldRecords.values()) {
12046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                record.disposeLocked(false);
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // Accumulate providers
12076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            providers.addAll(oldRecords.keySet());
12086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // update provider
12116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        for (String provider : providers) {
12126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // If provider is already disabled, don't need to do anything
1213b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            if (!isAllowedBySettingsLocked(provider, mCurrentUserId)) {
12146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                continue;
12156fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12176fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            applyRequirementsLocked(provider);
12186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
12196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
12224035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    public Location getLastLocation(LocationRequest request, String packageName) {
12236fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "getLastLocation: " + request);
12246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (request == null) request = DEFAULT_LOCATION_REQUEST;
122537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
12264035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        checkPackageName(packageName);
122737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
122837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                request.getProvider());
122937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        // no need to sanitize this request, as only the provider name is used
12304035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
1231b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        long identity = Binder.clearCallingIdentity();
1232b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        try {
1233b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            if (mBlacklist.isBlacklisted(packageName)) {
1234b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
1235b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        packageName);
123609016ab4dd056a16809419d612cb865a14980880Victoria Lease                return null;
123709016ab4dd056a16809419d612cb865a14980880Victoria Lease            }
1238b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease
1239b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            synchronized (mLock) {
1240b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                // Figure out the provider. Either its explicitly request (deprecated API's),
1241b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                // or use the fused provider
1242b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                String name = request.getProvider();
1243b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (name == null) name = LocationManager.FUSED_PROVIDER;
1244b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                LocationProviderInterface provider = mProvidersByName.get(name);
1245b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (provider == null) return null;
1246b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease
1247b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (!isAllowedBySettingsLocked(name, mCurrentUserId)) return null;
1248b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease
1249b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                Location location = mLastLocation.get(name);
1250b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (location == null) {
1251b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    return null;
1252b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                }
125337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
1254b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
1255b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    if (noGPSLocation != null) {
1256b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        return mLocationFudger.getOrCreate(noGPSLocation);
1257b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    }
125837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                } else {
125937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    return location;
126009016ab4dd056a16809419d612cb865a14980880Victoria Lease                }
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1262b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            return null;
1263b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        } finally {
1264b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            Binder.restoreCallingIdentity(identity);
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1268e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
12696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
12706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            String packageName) {
12716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (request == null) request = DEFAULT_LOCATION_REQUEST;
127237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
127337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
12746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkPendingIntent(intent);
12756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkPackageName(packageName);
127637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
127737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                request.getProvider());
127837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
12796fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
128037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
12816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
12822b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        // geo-fence manager uses the public location API, need to clear identity
12832b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        int uid = Binder.getCallingUid();
12842b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        long identity = Binder.clearCallingIdentity();
12852b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        try {
128637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            mGeofenceManager.addFence(sanitizedRequest, geofence, intent, uid, packageName);
12872b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        } finally {
12882b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly            Binder.restoreCallingIdentity(identity);
12892b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        }
12906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
12916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
12926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
12936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
129437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForGeofenceUse(getCallerAllowedResolutionLevel());
12956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkPendingIntent(intent);
12966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkPackageName(packageName);
12976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
12986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
12996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
13002b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        // geo-fence manager uses the public location API, need to clear identity
13012b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        long identity = Binder.clearCallingIdentity();
13022b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        try {
13032b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly            mGeofenceManager.removeFence(geofence, intent);
13042b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        } finally {
13052b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly            Binder.restoreCallingIdentity(identity);
13062b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        }
13076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
13086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
13096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
13106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean addGpsStatusListener(IGpsStatusListener listener) {
131215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mGpsStatusProvider == null) {
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
131537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
131637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                LocationManager.GPS_PROVIDER);
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
131915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            mGpsStatusProvider.addGpsStatusListener(listener);
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
13218a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "mGpsStatusProvider.addGpsStatusListener failed", e);
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1327e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeGpsStatusListener(IGpsStatusListener listener) {
13292f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
133015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            try {
133115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                mGpsStatusProvider.removeGpsStatusListener(listener);
133215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            } catch (Exception e) {
13338a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.e(TAG, "mGpsStatusProvider.removeGpsStatusListener failed", e);
133415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1338e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendExtraCommand(String provider, String command, Bundle extras) {
1340c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood        if (provider == null) {
1341c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood            // throw NullPointerException to remain compatible with previous implementation
1342c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood            throw new NullPointerException();
1343c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood        }
134437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
134537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                provider);
1346c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // and check for ACCESS_LOCATION_EXTRA_COMMANDS
1348b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood        if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13532f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
1354d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            LocationProviderInterface p = mProvidersByName.get(provider);
13556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (p == null) return false;
1356e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
1357d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            return p.sendExtraCommand(command, extras);
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1361e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
13626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public boolean sendNiResponse(int notifId, int userResponse) {
136318ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood        if (Binder.getCallingUid() != Process.myUid()) {
136418ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood            throw new SecurityException(
136518ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood                    "calling sendNiResponse from outside of the system is not allowed");
136618ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood        }
136722d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        try {
136822d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
13696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } catch (RemoteException e) {
13708a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
137122d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            return false;
137222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        }
137322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    }
137422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1376628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood     * @return null if the provider does not exist
1377f2db9fb0f877057a9ef56908d54f3c95fc3fd552Alexey Tarasov     * @throws SecurityException if the provider is not allowed to be
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * accessed by the caller
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1380e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
13816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public ProviderProperties getProviderProperties(String provider) {
1382b7f9d254978b285bf04613f6e69a1afa89240ca9Laurent Tu        if (mProvidersByName.get(provider) == null) {
1383b7f9d254978b285bf04613f6e69a1afa89240ca9Laurent Tu          return null;
1384b7f9d254978b285bf04613f6e69a1afa89240ca9Laurent Tu        }
1385b7f9d254978b285bf04613f6e69a1afa89240ca9Laurent Tu
138637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
138737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                provider);
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        LocationProviderInterface p;
13906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        synchronized (mLock) {
13916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            p = mProvidersByName.get(provider);
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (p == null) return null;
13956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        return p.getProperties();
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1398e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isProviderEnabled(String provider) {
140037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
140137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                provider);
14026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
14036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1404b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        long identity = Binder.clearCallingIdentity();
1405b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        try {
1406b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            synchronized (mLock) {
1407b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                LocationProviderInterface p = mProvidersByName.get(provider);
1408b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (p == null) return false;
14096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1410b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                return isAllowedBySettingsLocked(provider, mCurrentUserId);
1411b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            }
1412b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        } finally {
1413b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            Binder.restoreCallingIdentity(identity);
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14176fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void checkCallerIsProvider() {
1418275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
14196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                == PackageManager.PERMISSION_GRANTED) {
14202eeeec248a38ff33999c83f4b8d5bab7d50e79d2Nick Pelly            return;
14212eeeec248a38ff33999c83f4b8d5bab7d50e79d2Nick Pelly        }
14222eeeec248a38ff33999c83f4b8d5bab7d50e79d2Nick Pelly
14236fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // Previously we only used the INSTALL_LOCATION_PROVIDER
14246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // check. But that is system or signature
14256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // protection level which is not flexible enough for
14266fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // providers installed oustide the system image. So
14276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // also allow providers with a UID matching the
14286fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // currently bound package name
14294e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood
14306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        int uid = Binder.getCallingUid();
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (mGeocodeProvider != null) {
14336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (doesPackageHaveUid(uid, mGeocodeProvider.getConnectedPackageName())) return;
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        for (LocationProviderProxy proxy : mProxyProviders) {
14366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (doesPackageHaveUid(uid, proxy.getConnectedPackageName())) return;
14376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
14386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
14396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                "or UID of a currently bound location provider");
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private boolean doesPackageHaveUid(int uid, String packageName) {
14436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (packageName == null) {
14446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return false;
14454a7b65e0d544ef1feff8e1e5789f469f89ebb85cMike Lockwood        }
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
14476fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            ApplicationInfo appInfo = mPackageManager.getApplicationInfo(packageName, 0);
14486fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (appInfo.uid != uid) {
14496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                return false;
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } catch (NameNotFoundException e) {
14526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return false;
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        return true;
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14576fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
14586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void reportLocation(Location location, boolean passive) {
14596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkCallerIsProvider();
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (!location.isComplete()) {
14626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            Log.w(TAG, "Dropping incomplete location: " + location);
14636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return;
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14666fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location);
14676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location);
14686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        m.arg1 = (passive ? 1 : 0);
14696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mLocationHandler.sendMessageAtFrontOfQueue(m);
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static boolean shouldBroadcastSafe(Location loc, Location lastLoc, UpdateRecord record) {
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Always broadcast the first update
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (lastLoc == null) {
14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1479f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly        // Check whether sufficient time has passed
14806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        long minTime = record.mRequest.getFastestInterval();
14814118012da9a22694b3353040a485f8cdc27e2f17Philip Milne        long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos()) / 1000000L;
14826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Check whether sufficient distance has been traveled
14876fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        double minDistance = record.mRequest.getSmallestDisplacement();
14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (minDistance > 0.0) {
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (loc.distanceTo(lastLoc) <= minDistance) {
14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1497a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood    private void handleLocationChangedLocked(Location location, boolean passive) {
14984e31c4fffbc42b4c2b5dca6431cfeef9e078f5b4Nick Pelly        if (D) Log.d(TAG, "incoming location: " + location);
14994e31c4fffbc42b4c2b5dca6431cfeef9e078f5b4Nick Pelly
15006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        long now = SystemClock.elapsedRealtime();
1501a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
150360ec50a850ac7265b662df3c872583b6ef581ef8Laurent Tu        // Skip if the provider is unknown.
1504d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
15056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (p == null) return;
15066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
15076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // Update last known locations
150809016ab4dd056a16809419d612cb865a14980880Victoria Lease        Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
150909016ab4dd056a16809419d612cb865a14980880Victoria Lease        Location lastNoGPSLocation = null;
15106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Location lastLocation = mLastLocation.get(provider);
15114e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        if (lastLocation == null) {
15126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            lastLocation = new Location(provider);
15136fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mLastLocation.put(provider, lastLocation);
151409016ab4dd056a16809419d612cb865a14980880Victoria Lease        } else {
151509016ab4dd056a16809419d612cb865a14980880Victoria Lease            lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
151609016ab4dd056a16809419d612cb865a14980880Victoria Lease            if (noGPSLocation == null && lastNoGPSLocation != null) {
151709016ab4dd056a16809419d612cb865a14980880Victoria Lease                // New location has no no-GPS location: adopt last no-GPS location. This is set
151809016ab4dd056a16809419d612cb865a14980880Victoria Lease                // directly into location because we do not want to notify COARSE clients.
151909016ab4dd056a16809419d612cb865a14980880Victoria Lease                location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
152009016ab4dd056a16809419d612cb865a14980880Victoria Lease            }
15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        lastLocation.set(location);
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
152460ec50a850ac7265b662df3c872583b6ef581ef8Laurent Tu        // Skip if there are no UpdateRecords for this provider.
152560ec50a850ac7265b662df3c872583b6ef581ef8Laurent Tu        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
152660ec50a850ac7265b662df3c872583b6ef581ef8Laurent Tu        if (records == null || records.size() == 0) return;
152760ec50a850ac7265b662df3c872583b6ef581ef8Laurent Tu
152809016ab4dd056a16809419d612cb865a14980880Victoria Lease        // Fetch coarse location
152909016ab4dd056a16809419d612cb865a14980880Victoria Lease        Location coarseLocation = null;
153009016ab4dd056a16809419d612cb865a14980880Victoria Lease        if (noGPSLocation != null && !noGPSLocation.equals(lastNoGPSLocation)) {
153109016ab4dd056a16809419d612cb865a14980880Victoria Lease            coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
153209016ab4dd056a16809419d612cb865a14980880Victoria Lease        }
153309016ab4dd056a16809419d612cb865a14980880Victoria Lease
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Fetch latest status update time
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long newStatusUpdateTime = p.getStatusUpdateTime();
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15377ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood       // Get latest status
15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bundle extras = new Bundle();
15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int status = p.getStatus(extras);
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<Receiver> deadReceivers = null;
15426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        ArrayList<UpdateRecord> deadUpdateRecords = null;
1543e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Broadcast location or status to all listeners
15456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        for (UpdateRecord r : records) {
15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Receiver receiver = r.mReceiver;
154703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            boolean receiverDead = false;
15484035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
1549b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            int receiverUserId = UserHandle.getUserId(receiver.mUid);
1550b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            if (receiverUserId != mCurrentUserId) {
1551b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (D) {
1552b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    Log.d(TAG, "skipping loc update for background user " + receiverUserId +
1553b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                            " (current user: " + mCurrentUserId + ", app: " +
1554b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                            receiver.mPackageName + ")");
1555b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                }
1556b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                continue;
1557b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            }
1558b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease
15594035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            if (mBlacklist.isBlacklisted(receiver.mPackageName)) {
15604035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
15614035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                        receiver.mPackageName);
15624035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                continue;
15634035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            }
15644035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
156509016ab4dd056a16809419d612cb865a14980880Victoria Lease            Location notifyLocation = null;
156637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
156737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                notifyLocation = coarseLocation;  // use coarse location
15686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            } else {
156937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                notifyLocation = lastLocation;  // use fine location
15706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
157109016ab4dd056a16809419d612cb865a14980880Victoria Lease            if (notifyLocation != null) {
157209016ab4dd056a16809419d612cb865a14980880Victoria Lease                Location lastLoc = r.mLastFixBroadcast;
157309016ab4dd056a16809419d612cb865a14980880Victoria Lease                if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r)) {
157409016ab4dd056a16809419d612cb865a14980880Victoria Lease                    if (lastLoc == null) {
157509016ab4dd056a16809419d612cb865a14980880Victoria Lease                        lastLoc = new Location(notifyLocation);
157609016ab4dd056a16809419d612cb865a14980880Victoria Lease                        r.mLastFixBroadcast = lastLoc;
157709016ab4dd056a16809419d612cb865a14980880Victoria Lease                    } else {
157809016ab4dd056a16809419d612cb865a14980880Victoria Lease                        lastLoc.set(notifyLocation);
157909016ab4dd056a16809419d612cb865a14980880Victoria Lease                    }
158009016ab4dd056a16809419d612cb865a14980880Victoria Lease                    if (!receiver.callLocationChangedLocked(notifyLocation)) {
158109016ab4dd056a16809419d612cb865a14980880Victoria Lease                        Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
158209016ab4dd056a16809419d612cb865a14980880Victoria Lease                        receiverDead = true;
158309016ab4dd056a16809419d612cb865a14980880Victoria Lease                    }
15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15872f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            long prevStatusUpdateTime = r.mLastStatusBroadcast;
15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((newStatusUpdateTime > prevStatusUpdateTime) &&
158909016ab4dd056a16809419d612cb865a14980880Victoria Lease                    (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15912f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                r.mLastStatusBroadcast = newStatusUpdateTime;
15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!receiver.callStatusChangedLocked(provider, status, extras)) {
159303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    receiverDead = true;
15948a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
159503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                }
159603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            }
159703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
15986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // track expired records
15996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (r.mRequest.getNumUpdates() == 0 || r.mRequest.getExpireAt() < now) {
16006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                if (deadUpdateRecords == null) {
16016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    deadUpdateRecords = new ArrayList<UpdateRecord>();
16026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                }
16036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                deadUpdateRecords.add(r);
16046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
16056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // track dead receivers
16066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (receiverDead) {
160703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                if (deadReceivers == null) {
160803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    deadReceivers = new ArrayList<Receiver>();
160903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                }
161003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                if (!deadReceivers.contains(receiver)) {
161103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    deadReceivers.add(receiver);
16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1615e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
16166fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // remove dead records and receivers outside the loop
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (deadReceivers != null) {
16186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (Receiver receiver : deadReceivers) {
16196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                removeUpdatesLocked(receiver);
16206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
16216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
16226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (deadUpdateRecords != null) {
16236fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (UpdateRecord r : deadUpdateRecords) {
16246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                r.disposeLocked(true);
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class LocationWorkerHandler extends Handler {
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void handleMessage(Message msg) {
16326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            switch (msg.what) {
16336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                case MSG_LOCATION_CHANGED:
16346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    handleLocationChanged((Location) msg.obj, msg.arg1 == 1);
16356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    break;
16366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
16376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
16386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
163998cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood
16406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void handleLocationChanged(Location location, boolean passive) {
16416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        String provider = location.getProvider();
16426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
16436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (!passive) {
16446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // notify passive provider of the new location
16456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mPassiveProvider.updateLocation(location);
16466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
16476fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
16486fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        synchronized (mLock) {
1649b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            if (isAllowedBySettingsLocked(provider, mCurrentUserId)) {
16506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                handleLocationChangedLocked(location, passive);
16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final PackageMonitor mPackageMonitor = new PackageMonitor() {
16560528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        @Override
16576fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        public void onPackageDisappeared(String packageName, int reason) {
16586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // remove all receivers associated with this package name
16596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            synchronized (mLock) {
16606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                ArrayList<Receiver> deadReceivers = null;
16616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
16626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                for (Receiver receiver : mReceivers.values()) {
16636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    if (receiver.mPackageName.equals(packageName)) {
16646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                        if (deadReceivers == null) {
16656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                            deadReceivers = new ArrayList<Receiver>();
16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
16676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                        deadReceivers.add(receiver);
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // perform removal outside of mReceivers loop
16726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                if (deadReceivers != null) {
16736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    for (Receiver receiver : deadReceivers) {
16746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                        removeUpdatesLocked(receiver);
16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16790528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    };
16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Wake locks
16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16830528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    private void incrementPendingBroadcasts() {
16840528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        synchronized (mWakeLock) {
16850528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (mPendingBroadcasts++ == 0) {
16860528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                try {
16870528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    mWakeLock.acquire();
16880528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    log("Acquired wakelock");
16890528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                } catch (Exception e) {
16900528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // This is to catch a runtime exception thrown when we try to release an
16910528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // already released lock.
16928a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.e(TAG, "exception in acquireWakeLock()", e);
16930528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                }
16940528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
169548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
169648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
169748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
169848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private void decrementPendingBroadcasts() {
16990528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        synchronized (mWakeLock) {
170048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (--mPendingBroadcasts == 0) {
17010528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                try {
17020528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // Release wake lock
17030528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    if (mWakeLock.isHeld()) {
17040528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                        mWakeLock.release();
17050528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                        log("Released wakelock");
17060528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    } else {
17070528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                        log("Can't release wakelock again!");
17080528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    }
17090528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                } catch (Exception e) {
17100528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // This is to catch a runtime exception thrown when we try to release an
17110528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                    // already released lock.
17128a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.e(TAG, "exception in releaseWakeLock()", e);
17130528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                }
171448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
171548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
171648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
171748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
17189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Geocoder
17199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1720e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
1721e15735a9e0c0b1448b68f2d6b3247404fc1df417Mike Lockwood    public boolean geocoderIsPresent() {
172201ac80b715881db22bde8b31633dd8a4dc375389Mark Vandevoorde        return mGeocodeProvider != null;
172301ac80b715881db22bde8b31633dd8a4dc375389Mark Vandevoorde    }
172401ac80b715881db22bde8b31633dd8a4dc375389Mark Vandevoorde
1725e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String getFromLocation(double latitude, double longitude, int maxResults,
172734901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwood            GeocoderParams params, List<Address> addrs) {
1728a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        if (mGeocodeProvider != null) {
1729628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood            return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
1730628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                    params, addrs);
17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1732a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        return null;
17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1735a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood
1736e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
17379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String getFromLocationName(String locationName,
1738a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            double lowerLeftLatitude, double lowerLeftLongitude,
1739a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            double upperRightLatitude, double upperRightLongitude, int maxResults,
174034901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwood            GeocoderParams params, List<Address> addrs) {
1741a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood
1742a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        if (mGeocodeProvider != null) {
1743628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood            return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
1744628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                    lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
1745628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                    maxResults, params, addrs);
17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1747a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        return null;
17489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Mock Providers
17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void checkMockPermissionsSafe() {
17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(),
17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1;
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!allowMocks) {
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting");
17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) !=
17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PackageManager.PERMISSION_GRANTED) {
17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission");
1762e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        }
17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1765e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
17666fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void addTestProvider(String name, ProviderProperties properties) {
17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1769a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
1770a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood            throw new IllegalArgumentException("Cannot mock the passive location provider");
1771a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        }
1772a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood
177386328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood        long identity = Binder.clearCallingIdentity();
17742f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
17756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            MockProvider provider = new MockProvider(name, this, properties);
17767566c1debebe072af76411e11d96810fd1409482Mike Lockwood            // remove the real provider if we are replacing GPS or network provider
17777566c1debebe072af76411e11d96810fd1409482Mike Lockwood            if (LocationManager.GPS_PROVIDER.equals(name)
17781332b53522e281012fefb34bfbcc68a03028f516Nick Pelly                    || LocationManager.NETWORK_PROVIDER.equals(name)
17791332b53522e281012fefb34bfbcc68a03028f516Nick Pelly                    || LocationManager.FUSED_PROVIDER.equals(name)) {
1780d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                LocationProviderInterface p = mProvidersByName.get(name);
1781d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                if (p != null) {
17826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    removeProviderLocked(p);
17837566c1debebe072af76411e11d96810fd1409482Mike Lockwood                }
17847566c1debebe072af76411e11d96810fd1409482Mike Lockwood            }
178515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (mProvidersByName.get(name) != null) {
17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            addProviderLocked(provider);
17897ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mMockProviders.put(name, provider);
17906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mLastLocation.put(name, null);
17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
17929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
179386328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood        Binder.restoreCallingIdentity(identity);
17949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1796e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeTestProvider(String provider) {
17989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
17992f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18007ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18017ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
180486328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            long identity = Binder.clearCallingIdentity();
18056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            removeProviderLocked(mProvidersByName.get(provider));
18067ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mMockProviders.remove(mockProvider);
18076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
18086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // reinstate real provider if available
18096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            LocationProviderInterface realProvider = mRealProviders.get(provider);
18106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (realProvider != null) {
18116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                addProviderLocked(realProvider);
18126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
18136fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mLastLocation.put(provider, null);
18149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
181586328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            Binder.restoreCallingIdentity(identity);
18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1819e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderLocation(String provider, Location loc) {
18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18222f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18237ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18247ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
182795427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
182895427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            long identity = Binder.clearCallingIdentity();
18297ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.setLocation(loc);
183095427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            Binder.restoreCallingIdentity(identity);
18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1834e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
18359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderLocation(String provider) {
18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18372f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18387ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18397ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18427ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.clearLocation();
18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1846e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
18479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderEnabled(String provider, boolean enabled) {
18489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18492f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18507ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18517ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
185486328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            long identity = Binder.clearCallingIdentity();
18559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (enabled) {
18567ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                mockProvider.enable();
18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEnabledProviders.add(provider);
18589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDisabledProviders.remove(provider);
18599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
18607ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                mockProvider.disable();
18619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEnabledProviders.remove(provider);
18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDisabledProviders.add(provider);
18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
186586328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            Binder.restoreCallingIdentity(identity);
18669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1869e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
18709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderEnabled(String provider) {
18719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18722f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18737ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18747ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
187786328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            long identity = Binder.clearCallingIdentity();
18789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEnabledProviders.remove(provider);
18799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDisabledProviders.remove(provider);
18809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
188186328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            Binder.restoreCallingIdentity(identity);
18829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1885e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
18879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
18882f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
18897ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
18907ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
18919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
18929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18937ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.setStatus(status, extras, updateTime);
18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1897e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
18989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderStatus(String provider) {
18999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
19002f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
19017ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
19027ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19057ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.clearStatus();
19069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void log(String log) {
19109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Log.isLoggable(TAG, Log.VERBOSE)) {
19118a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.d(TAG, log);
19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1914e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
1915e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
19179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
19190528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            pw.println("Permission Denial: can't dump LocationManagerService from from pid="
19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Binder.getCallingPid()
19219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", uid=" + Binder.getCallingUid());
19229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
19239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1924e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
19252f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
19269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("Current Location Manager state:");
19279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Location Listeners:");
19286fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (Receiver receiver : mReceivers.values()) {
19296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                pw.println("    " + receiver);
19309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Records by Provider:");
19326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
19336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                pw.println("    " + entry.getKey() + ":");
19346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                for (UpdateRecord record : entry.getValue()) {
19356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    pw.println("      " + record);
19369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Last Known Locations:");
19396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
19406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                String provider = entry.getKey();
19416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                Location location = entry.getValue();
19426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                pw.println("    " + provider + ": " + location);
19439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1945e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly            mGeofenceManager.dump(pw);
19466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
19479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mEnabledProviders.size() > 0) {
19489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Enabled Providers:");
19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (String i : mEnabledProviders) {
19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i);
19519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1952e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
19539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mDisabledProviders.size() > 0) {
19559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Disabled Providers:");
19569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (String i : mDisabledProviders) {
19579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i);
19589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19604035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            pw.append("  ");
19614035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            mBlacklist.dump(pw);
19629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mMockProviders.size() > 0) {
19639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Mock Providers:");
19649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
19657ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                    i.getValue().dump(pw, "      ");
19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
19679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
196974fa7eabda3d0c1a85e0b568e3fc4230ed4fe7a4Nick Pelly            pw.append("  fudger: ");
197074fa7eabda3d0c1a85e0b568e3fc4230ed4fe7a4Nick Pelly            mLocationFudger.dump(fd, pw,  args);
197174fa7eabda3d0c1a85e0b568e3fc4230ed4fe7a4Nick Pelly
19726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (args.length > 0 && "short".equals(args[0])) {
19736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                return;
19746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
19753c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger            for (LocationProviderInterface provider: mProviders) {
19766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                pw.print(provider.getName() + " Internal State");
19776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                if (provider instanceof LocationProviderProxy) {
19786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    LocationProviderProxy proxy = (LocationProviderProxy) provider;
19796fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    pw.print(" (" + proxy.getConnectedPackageName() + ")");
19803c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger                }
19816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                pw.println(":");
19826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                provider.dump(fd, pw, args);
19833c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger            }
19849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1987