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
19a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.app.AppOpsManager;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.PendingIntent;
2138389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Leaseimport android.content.BroadcastReceiver;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
2538389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Leaseimport android.content.IntentFilter;
266fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.content.pm.ApplicationInfo;
27fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamiltonimport android.content.pm.PackageInfo;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.content.pm.PackageManager.NameNotFoundException;
30fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamiltonimport android.content.pm.ResolveInfo;
31fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamiltonimport android.content.pm.Signature;
32628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwoodimport android.content.res.Resources;
33bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsuimport android.database.ContentObserver;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Address;
3503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwoodimport android.location.Criteria;
3634901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwoodimport android.location.GeocoderParams;
376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.location.Geofence;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.IGpsStatusListener;
3915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwoodimport android.location.IGpsStatusProvider;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.ILocationListener;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.ILocationManager;
4222d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xieimport android.location.INetInitiatedListener;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.Location;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationManager;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.location.LocationProvider;
466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.location.LocationRequest;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
513d12b51ee38537f6760a833618948f936e75561dMike Lockwoodimport android.os.Looper;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager;
54e932f7f2a47b770c636443d411436bd29cc4bb43Mike Lockwoodimport android.os.Process;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport android.os.SystemClock;
575ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackbornimport android.os.UserHandle;
587e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackbornimport android.os.WorkSource;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
618a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog;
62e97ae40dffe7d7f8917c51c4f3f6c1b18c238565Mike Lockwoodimport com.android.internal.content.PackageMonitor;
636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport com.android.internal.location.ProviderProperties;
646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport com.android.internal.location.ProviderRequest;
658d044e8bc287c1a567d82aedbe30085b011544c3Dianne Hackbornimport com.android.internal.os.BackgroundThread;
661af4b0280af406cfc7eb46810f6b76e57b983e11destradaaimport com.android.server.location.FlpHardwareProvider;
671af4b0280af406cfc7eb46810f6b76e57b983e11destradaaimport com.android.server.location.FusedProxy;
6843e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport com.android.server.location.GeocoderProxy;
698ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganeshimport com.android.server.location.GeofenceProxy;
70e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pellyimport com.android.server.location.GeofenceManager;
7143e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport com.android.server.location.GpsLocationProvider;
724035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pellyimport com.android.server.location.LocationBlacklist;
7374fa7eabda3d0c1a85e0b568e3fc4230ed4fe7a4Nick Pellyimport com.android.server.location.LocationFudger;
7443e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport com.android.server.location.LocationProviderInterface;
7543e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport com.android.server.location.LocationProviderProxy;
7643e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport com.android.server.location.MockProvider;
7743e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport com.android.server.location.PassiveProvider;
7843e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwood
7943e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.io.FileDescriptor;
8043e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.io.PrintWriter;
8143e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.util.ArrayList;
826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pellyimport java.util.Arrays;
8343e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.util.HashMap;
8443e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.util.HashSet;
8543e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.util.List;
8643e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.util.Map;
8743e33f28721e4759d4edb0fad08d330bba74f25eMike Lockwoodimport java.util.Set;
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The service class that manages LocationProviders and issues location
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * updates and alerts.
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
935cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Leasepublic class LocationManagerService extends ILocationManager.Stub {
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "LocationManagerService";
95f79811e7b9611066b3ca2df3ceea07bdd99597e9JP Abgrall    public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final String WAKELOCK_KEY = TAG;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    // Location resolution level: no location data whatsoever
10037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private static final int RESOLUTION_LEVEL_NONE = 0;
10137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    // Location resolution level: coarse location data only
10237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private static final int RESOLUTION_LEVEL_COARSE = 1;
10337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    // Location resolution level: fine location data
10437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private static final int RESOLUTION_LEVEL_FINE = 2;
10537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_MOCK_LOCATION =
1076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            android.Manifest.permission.ACCESS_MOCK_LOCATION;
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
1096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
110275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood    private static final String INSTALL_LOCATION_PROVIDER =
1116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
1126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1136fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final String NETWORK_LOCATION_SERVICE_ACTION =
11439062ddff24ce2a3e3a61ba1a087363842f9d1aeStan Chesnutt            "com.android.location.service.v3.NetworkLocationProvider";
1156fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final String FUSED_LOCATION_SERVICE_ACTION =
1166fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            "com.android.location.service.FusedLocationProvider";
1176fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final int MSG_LOCATION_CHANGED = 1;
1196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1201b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie    private static final long NANOS_PER_MILLI = 1000000L;
1211b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie
1220b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie    // The maximum interval a location request can have and still be considered "high power".
1230b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie    private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
1240b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie
125f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly    // Location Providers may sometimes deliver location updates
126f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly    // slightly faster that requested - provide grace period so
127f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly    // we don't unnecessarily filter events that are otherwise on
128f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly    // time
1296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
130f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly
1316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final Context mContext;
134a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private final AppOpsManager mAppOps;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // used internally for synchronization
1376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final Object mLock = new Object();
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1395cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease    // --- fields below are final after systemReady() ---
14074fa7eabda3d0c1a85e0b568e3fc4230ed4fe7a4Nick Pelly    private LocationFudger mLocationFudger;
1416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private GeofenceManager mGeofenceManager;
1426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private PackageManager mPackageManager;
1430aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease    private PowerManager mPowerManager;
144628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood    private GeocoderProxy mGeocodeProvider;
14515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    private IGpsStatusProvider mGpsStatusProvider;
14622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    private INetInitiatedListener mNetInitiatedListener;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private LocationWorkerHandler mLocationHandler;
1484035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    private PassiveProvider mPassiveProvider;  // track passive provider for special cases
1494035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    private LocationBlacklist mBlacklist;
1506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // --- fields below are protected by mLock ---
1526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // Set of providers that are explicitly enabled
1536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final Set<String> mEnabledProviders = new HashSet<String>();
1547566c1debebe072af76411e11d96810fd1409482Mike Lockwood
1556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // Set of providers that are explicitly disabled
1566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final Set<String> mDisabledProviders = new HashSet<String>();
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // Mock (test) providers
1596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final HashMap<String, MockProvider> mMockProviders =
1606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            new HashMap<String, MockProvider>();
161e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
1626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // all receivers
1632f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    private final HashMap<Object, Receiver> mReceivers = new HashMap<Object, Receiver>();
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // currently installed providers (with mocks replacing real providers)
166d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood    private final ArrayList<LocationProviderInterface> mProviders =
1676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            new ArrayList<LocationProviderInterface>();
16815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
1696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // real providers, saved here when mocked out
1706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final HashMap<String, LocationProviderInterface> mRealProviders =
1716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            new HashMap<String, LocationProviderInterface>();
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // mapping from provider name to provider
1746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final HashMap<String, LocationProviderInterface> mProvidersByName =
1756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            new HashMap<String, LocationProviderInterface>();
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // mapping from provider name to all its UpdateRecords
1786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
1796fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            new HashMap<String, ArrayList<UpdateRecord>>();
1806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // mapping from provider name to last known location
1826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final HashMap<String, Location> mLastLocation = new HashMap<String, Location>();
1837e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn
1841b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie    // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
1851b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie    // locations stored here are not fudged for coarse permissions.
1861b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie    private final HashMap<String, Location> mLastLocationCoarseInterval =
1871b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie            new HashMap<String, Location>();
1881b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie
1896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    // all providers that operate over proxy, for authorizing incoming location
1906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final ArrayList<LocationProviderProxy> mProxyProviders =
1916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            new ArrayList<LocationProviderProxy>();
1926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
19338389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease    // current active user on the device - other users are denied location data
19438389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease    private int mCurrentUserId = UserHandle.USER_OWNER;
19538389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease
1966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public LocationManagerService(Context context) {
1976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        super();
1986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mContext = context;
199a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
2006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "Constructed");
2026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // most startup is deferred until systemReady()
2046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
2056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
206a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public void systemRunning() {
2075cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease        synchronized (mLock) {
2085cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease            if (D) Log.d(TAG, "systemReady()");
2096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2105cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease            // fetch package manager
2115cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease            mPackageManager = mContext.getPackageManager();
2126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2130aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease            // fetch power manager
2140aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease            mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
2156fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2165cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease            // prepare worker thread
2178d044e8bc287c1a567d82aedbe30085b011544c3Dianne Hackborn            mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper());
2186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
2195cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease            // prepare mLocationHandler's dependents
2205cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease            mLocationFudger = new LocationFudger(mContext, mLocationHandler);
2215cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease            mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
2225cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease            mBlacklist.init();
2235cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease            mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
224bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu
225c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            // Monitor for app ops mode changes.
2269bb0ee9131b0fa8cf2720f200575ba2ede48a65cDianne Hackborn            AppOpsManager.OnOpChangedListener callback
2279bb0ee9131b0fa8cf2720f200575ba2ede48a65cDianne Hackborn                    = new AppOpsManager.OnOpChangedInternalListener() {
2289bb0ee9131b0fa8cf2720f200575ba2ede48a65cDianne Hackborn                public void onOpChanged(int op, String packageName) {
229c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    synchronized (mLock) {
2301304f4ae32cf7121fe11e95f2a7151ea208b6ccaDianne Hackborn                        for (Receiver receiver : mReceivers.values()) {
2311304f4ae32cf7121fe11e95f2a7151ea208b6ccaDianne Hackborn                            receiver.updateMonitoring(true);
2321304f4ae32cf7121fe11e95f2a7151ea208b6ccaDianne Hackborn                        }
233c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        applyAllProviderRequirementsLocked();
234c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    }
235c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
236c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            };
237c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null, callback);
238c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
2395cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease            // prepare providers
2406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            loadProvidersLocked();
2415cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease            updateProvidersLocked();
2426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
243bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu
2446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // listen for settings changes
245bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu        mContext.getContentResolver().registerContentObserver(
24675defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu                Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
247bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu                new ContentObserver(mLocationHandler) {
2485cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease                    @Override
2495cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease                    public void onChange(boolean selfChange) {
2505cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease                        synchronized (mLock) {
2515cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease                            updateProvidersLocked();
2525cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease                        }
2535cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease                    }
2545cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease                }, UserHandle.USER_ALL);
2555cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease        mPackageMonitor.register(mContext, mLocationHandler.getLooper(), true);
256bb95cb9f997afc34d54f3d5bcb247c44f368b62bBrian Muramatsu
25738389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        // listen for user change
25838389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        IntentFilter intentFilter = new IntentFilter();
25938389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
26038389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease
26138389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        mContext.registerReceiverAsUser(new BroadcastReceiver() {
26238389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease            @Override
26338389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease            public void onReceive(Context context, Intent intent) {
26438389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease                String action = intent.getAction();
26538389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease                if (Intent.ACTION_USER_SWITCHED.equals(action)) {
26638389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease                    switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
26738389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease                }
26838389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease            }
2695cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease        }, UserHandle.ALL, intentFilter, null, mLocationHandler);
2706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
2716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
272fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton    private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) {
273fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        PackageManager pm = mContext.getPackageManager();
274fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        String systemPackageName = mContext.getPackageName();
275fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
276fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
277fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
278fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                new Intent(FUSED_LOCATION_SERVICE_ACTION),
279fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                PackageManager.GET_META_DATA, mCurrentUserId);
280fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        for (ResolveInfo rInfo : rInfos) {
281fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            String packageName = rInfo.serviceInfo.packageName;
282fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
283fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            // Check that the signature is in the list of supported sigs. If it's not in
284fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            // this list the standard provider binding logic won't bind to it.
285fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            try {
286fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                PackageInfo pInfo;
287fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
288fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
289fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                    Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
290fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                            ", but has wrong signature, ignoring");
291fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                    continue;
292fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                }
293fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            } catch (NameNotFoundException e) {
294fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                Log.e(TAG, "missing package: " + packageName);
295fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                continue;
296fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            }
297fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
298fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            // Get the version info
299fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            if (rInfo.serviceInfo.metaData == null) {
300fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                Log.w(TAG, "Found fused provider without metadata: " + packageName);
301fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                continue;
302fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            }
303fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
304fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            int version = rInfo.serviceInfo.metaData.getInt(
305fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                    ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
306fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            if (version == 0) {
307fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                // This should be the fallback fused location provider.
308fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
309fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                // Make sure it's in the system partition.
310fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
311fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                    if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
312fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                    continue;
313fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                }
314fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
315fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                // Check that the fallback is signed the same as the OS
316fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                // as a proxy for coreApp="true"
317fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                if (pm.checkSignatures(systemPackageName, packageName)
318fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                        != PackageManager.SIGNATURE_MATCH) {
319fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                    if (D) Log.d(TAG, "Fallback candidate not signed the same as system: "
320fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                            + packageName);
321fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                    continue;
322fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                }
323fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
324fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                // Found a valid fallback.
325fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                if (D) Log.d(TAG, "Found fallback provider: " + packageName);
326fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                return;
327fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            } else {
328fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
329fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton            }
330fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        }
331fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
332fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        throw new IllegalStateException("Unable to find a fused location provider that is in the "
333fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                + "system partition with version 0 and signed with the platform certificate. "
334fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                + "Such a package is needed to provide a default fused location provider in the "
335fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                + "event that no other fused location provider has been installed or is currently "
336fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                + "available. For example, coreOnly boot mode when decrypting the data "
337fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
338fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton    }
339fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
3406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void loadProvidersLocked() {
3415c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        // create a passive location provider, which is always enabled
3425c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        PassiveProvider passiveProvider = new PassiveProvider(this);
3435c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        addProviderLocked(passiveProvider);
3445c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        mEnabledProviders.add(passiveProvider.getName());
3455c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease        mPassiveProvider = passiveProvider;
3468ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        // Create a gps location provider
3478ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh        GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this,
3488ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh                mLocationHandler.getLooper());
3495c24fd03426db58b63e1a792c2595447cb722d46Victoria Lease
3506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (GpsLocationProvider.isSupported()) {
3516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
3526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
3536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            addProviderLocked(gpsProvider);
3546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mRealProviders.put(LocationManager.GPS_PROVIDER, gpsProvider);
3556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3576fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        /*
3586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Load package name(s) containing location provider support.
3596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        These packages can contain services implementing location providers:
3606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Geocoder Provider, Network Location Provider, and
3616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Fused Location Provider. They will each be searched for
3626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        service components implementing these providers.
3636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        The location framework also has support for installation
3646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        of new location providers at run-time. The new package does not
3656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        have to be explicitly listed here, however it must have a signature
3666fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        that matches the signature of at least one package on this list.
3676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        */
3686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Resources resources = mContext.getResources();
3696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        ArrayList<String> providerPackageNames = new ArrayList<String>();
370fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        String[] pkgs = resources.getStringArray(
3716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                com.android.internal.R.array.config_locationProviderPackageNames);
372fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        if (D) Log.d(TAG, "certificates for location providers pulled from: " +
373fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton                Arrays.toString(pkgs));
374fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));
375fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton
376fbadb69978be578cea9d2bf038de7c79b0787e4fJeff Hamilton        ensureFallbackFusedProviderPresentLocked(providerPackageNames);
3776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
3786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // bind to network provider
3796fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
3806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                mContext,
3816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                LocationManager.NETWORK_PROVIDER,
3826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                NETWORK_LOCATION_SERVICE_ACTION,
383c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun                com.android.internal.R.bool.config_enableNetworkLocationOverlay,
384c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun                com.android.internal.R.string.config_networkLocationProviderPackageName,
385c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun                com.android.internal.R.array.config_locationProviderPackageNames,
386c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun                mLocationHandler);
3876fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (networkProvider != null) {
3886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
3896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mProxyProviders.add(networkProvider);
3906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            addProviderLocked(networkProvider);
3916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else {
3926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            Slog.w(TAG,  "no network location provider found");
3936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
3946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
3956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // bind to fused provider
3966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(
3976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                mContext,
3986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                LocationManager.FUSED_PROVIDER,
3996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                FUSED_LOCATION_SERVICE_ACTION,
400c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun                com.android.internal.R.bool.config_enableFusedLocationOverlay,
401c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun                com.android.internal.R.string.config_fusedLocationProviderPackageName,
402c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun                com.android.internal.R.array.config_locationProviderPackageNames,
403c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun                mLocationHandler);
4046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (fusedLocationProvider != null) {
4056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            addProviderLocked(fusedLocationProvider);
4066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mProxyProviders.add(fusedLocationProvider);
4076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mEnabledProviders.add(fusedLocationProvider.getName());
408c3575188c2f2ad27b1f03b9b9c0705a686a5e42fKenny Root            mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
4096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else {
4106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            Slog.e(TAG, "no fused location provider found",
4116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    new IllegalStateException("Location service needs a fused location provider"));
4126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // bind to geocoder provider
415c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun        mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
416c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun                com.android.internal.R.bool.config_enableGeocoderOverlay,
417c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun                com.android.internal.R.string.config_geocoderProviderPackageName,
418c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun                com.android.internal.R.array.config_locationProviderPackageNames,
41903cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease                mLocationHandler);
4206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (mGeocodeProvider == null) {
4216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            Slog.e(TAG,  "no geocoder provider found");
4226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
4238ce470dd4ba0608abb6b5eae117cefca927af96bJaikumar Ganesh
4241af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        // bind to fused provider
4251af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
4261af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        FusedProxy fusedProxy = FusedProxy.createAndBind(
4271af4b0280af406cfc7eb46810f6b76e57b983e11destradaa                mContext,
4281af4b0280af406cfc7eb46810f6b76e57b983e11destradaa                mLocationHandler,
42964be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                flpHardwareProvider.getLocationHardware(),
43064be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                com.android.internal.R.bool.config_enableFusedLocationOverlay,
43164be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                com.android.internal.R.string.config_fusedLocationProviderPackageName,
43264be0c617f902398cbbcc2b145c86a8fbfc2feacdestradaa                com.android.internal.R.array.config_locationProviderPackageNames);
4331af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        if(fusedProxy == null) {
4341af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            Slog.e(TAG, "No FusedProvider found.");
4351af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        }
4360682809ad08db284d7110aab44108d5e9c310e6bdestradaa
4370682809ad08db284d7110aab44108d5e9c310e6bdestradaa        // bind to geofence provider
4380682809ad08db284d7110aab44108d5e9c310e6bdestradaa        GeofenceProxy provider = GeofenceProxy.createAndBind(mContext,
4390682809ad08db284d7110aab44108d5e9c310e6bdestradaa                com.android.internal.R.bool.config_enableGeofenceOverlay,
4400682809ad08db284d7110aab44108d5e9c310e6bdestradaa                com.android.internal.R.string.config_geofenceProviderPackageName,
4410682809ad08db284d7110aab44108d5e9c310e6bdestradaa                com.android.internal.R.array.config_locationProviderPackageNames,
4420682809ad08db284d7110aab44108d5e9c310e6bdestradaa                mLocationHandler,
4430682809ad08db284d7110aab44108d5e9c310e6bdestradaa                gpsProvider.getGpsGeofenceProxy(),
4440682809ad08db284d7110aab44108d5e9c310e6bdestradaa                flpHardwareProvider.getGeofenceHardware());
4450682809ad08db284d7110aab44108d5e9c310e6bdestradaa        if (provider == null) {
4460682809ad08db284d7110aab44108d5e9c310e6bdestradaa            Slog.e(TAG,  "no geofence provider found");
4470682809ad08db284d7110aab44108d5e9c310e6bdestradaa        }
4486fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
4499637d474899d9725da8a41fdf92b9bd1a15d301eMike Lockwood
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
45138389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease     * Called when the device's active user changes.
45238389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease     * @param userId the new active user's UserId
45338389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease     */
45438389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease    private void switchUser(int userId) {
45583762d22c9bde92d412cf5a263a228d705606721Victoria Lease        mBlacklist.switchUser(userId);
45603cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease        mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
45738389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        synchronized (mLock) {
458b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            mLastLocation.clear();
4591b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie            mLastLocationCoarseInterval.clear();
460b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            for (LocationProviderInterface p : mProviders) {
461b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                updateProviderListenersLocked(p.getName(), false, mCurrentUserId);
462b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            }
46338389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease            mCurrentUserId = userId;
464b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            updateProvidersLocked();
46538389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease        }
46638389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease    }
46738389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease
46838389b6cf7bd2ef49d2bd20ff1bca8677596590eVictoria Lease    /**
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * A wrapper class holding either an ILocationListener or a PendingIntent to receive
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * location updates.
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
47248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
4736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final int mUid;  // uid of receiver
4746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final int mPid;  // pid of receiver
4756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final String mPackageName;  // package name of receiver
47637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        final int mAllowedResolutionLevel;  // resolution level allowed to receiver
4776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ILocationListener mListener;
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final PendingIntent mPendingIntent;
48082edc9b3482307a8e93655aadabb4f9ad24efe46David Christie        final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
48140e5782f5c79ea660b98b8875086f592367bc1d2David Christie        final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Object mKey;
4836fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
4842f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
485f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly
4860b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie        // True if app ops has started monitoring this receiver for locations.
4871304f4ae32cf7121fe11e95f2a7151ea208b6ccaDianne Hackborn        boolean mOpMonitoring;
4880b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie        // True if app ops has started monitoring this receiver for high power (gps) locations.
4890b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie        boolean mOpHighPowerMonitoring;
49048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        int mPendingBroadcasts;
4910aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease        PowerManager.WakeLock mWakeLock;
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
49440e5782f5c79ea660b98b8875086f592367bc1d2David Christie                String packageName, WorkSource workSource, boolean hideFromAppOps) {
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mListener = listener;
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPendingIntent = intent;
4976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (listener != null) {
4986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                mKey = listener.asBinder();
4996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            } else {
5006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                mKey = intent;
5016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
50237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
5036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mUid = uid;
5046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mPid = pid;
5056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mPackageName = packageName;
50682edc9b3482307a8e93655aadabb4f9ad24efe46David Christie            if (workSource != null && workSource.size() <= 0) {
50782edc9b3482307a8e93655aadabb4f9ad24efe46David Christie                workSource = null;
50882edc9b3482307a8e93655aadabb4f9ad24efe46David Christie            }
50982edc9b3482307a8e93655aadabb4f9ad24efe46David Christie            mWorkSource = workSource;
51040e5782f5c79ea660b98b8875086f592367bc1d2David Christie            mHideFromAppOps = hideFromAppOps;
5110aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease
5121304f4ae32cf7121fe11e95f2a7151ea208b6ccaDianne Hackborn            updateMonitoring(true);
5131304f4ae32cf7121fe11e95f2a7151ea208b6ccaDianne Hackborn
5140aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease            // construct/configure wakelock
5150aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease            mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
51682edc9b3482307a8e93655aadabb4f9ad24efe46David Christie            if (workSource == null) {
51782edc9b3482307a8e93655aadabb4f9ad24efe46David Christie                workSource = new WorkSource(mUid, mPackageName);
51882edc9b3482307a8e93655aadabb4f9ad24efe46David Christie            }
51982edc9b3482307a8e93655aadabb4f9ad24efe46David Christie            mWakeLock.setWorkSource(workSource);
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean equals(Object otherObj) {
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (otherObj instanceof Receiver) {
5256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                return mKey.equals(((Receiver)otherObj).mKey);
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int hashCode() {
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mKey.hashCode();
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5343681f2614fa8c10560c790f6b4287f65d6fd2663Mike Lockwood
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
5376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            StringBuilder s = new StringBuilder();
5386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append("Reciever[");
5396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append(Integer.toHexString(System.identityHashCode(this)));
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
5416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                s.append(" listener");
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
5436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                s.append(" intent");
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (String p : mUpdateRecords.keySet()) {
5466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                s.append(" ").append(mUpdateRecords.get(p).toString());
5476fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
5486fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append("]");
5496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return s.toString();
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
55215b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie        /**
55315b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie         * Update AppOp monitoring for this receiver.
55415b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie         *
55515b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie         * @param allow If true receiver is currently active, if false it's been removed.
55615b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie         */
5571304f4ae32cf7121fe11e95f2a7151ea208b6ccaDianne Hackborn        public void updateMonitoring(boolean allow) {
55840e5782f5c79ea660b98b8875086f592367bc1d2David Christie            if (mHideFromAppOps) {
55940e5782f5c79ea660b98b8875086f592367bc1d2David Christie                return;
56040e5782f5c79ea660b98b8875086f592367bc1d2David Christie            }
56140e5782f5c79ea660b98b8875086f592367bc1d2David Christie
56215b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie            boolean requestingLocation = false;
56315b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie            boolean requestingHighPowerLocation = false;
56415b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie            if (allow) {
56515b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                // See if receiver has any enabled update records.  Also note if any update records
56615b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                // are high power (has a high power provider with an interval under a threshold).
56715b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                for (UpdateRecord updateRecord : mUpdateRecords.values()) {
56815b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                    if (isAllowedByCurrentUserSettingsLocked(updateRecord.mProvider)) {
56915b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                        requestingLocation = true;
57015b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                        LocationProviderInterface locationProvider
57115b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                            = mProvidersByName.get(updateRecord.mProvider);
57215b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                        ProviderProperties properties = locationProvider != null
57315b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                                ? locationProvider.getProperties() : null;
57415b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                        if (properties != null
57515b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                                && properties.mPowerRequirement == Criteria.POWER_HIGH
57615b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                                && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
57715b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                            requestingHighPowerLocation = true;
57815b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                            break;
57915b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                        }
58015b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                    }
58115b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                }
58215b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie            }
58315b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie
5840b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie            // First update monitoring of any location request (including high power).
58515b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie            mOpMonitoring = updateMonitoring(
58615b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                    requestingLocation,
58715b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                    mOpMonitoring,
5880b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie                    AppOpsManager.OP_MONITOR_LOCATION);
5890b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie
5900b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie            // Now update monitoring of high power requests only.
591c750c1fb83fbdec895e236dda7207db4da14ec49David Christie            boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
59215b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie            mOpHighPowerMonitoring = updateMonitoring(
59315b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                    requestingHighPowerLocation,
59415b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                    mOpHighPowerMonitoring,
5950b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie                    AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
596c750c1fb83fbdec895e236dda7207db4da14ec49David Christie            if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
59715b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie                // Send an intent to notify that a high power request has been added/removed.
598c750c1fb83fbdec895e236dda7207db4da14ec49David Christie                Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
599c750c1fb83fbdec895e236dda7207db4da14ec49David Christie                mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
600c750c1fb83fbdec895e236dda7207db4da14ec49David Christie            }
6010b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie        }
6020b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie
6030b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie        /**
6040b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie         * Update AppOps monitoring for a single location request and op type.
6050b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie         *
6060b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie         * @param allowMonitoring True if monitoring is allowed for this request/op.
6070b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie         * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
6080b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie         * @param op AppOps code for the op to update.
6090b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie         * @return True if monitoring is on for this request/op after updating.
6100b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie         */
6110b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie        private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
6120b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie                int op) {
6130b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie            if (!currentlyMonitoring) {
6140b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie                if (allowMonitoring) {
6150b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie                    return mAppOps.startOpNoThrow(op, mUid, mPackageName)
6160b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie                            == AppOpsManager.MODE_ALLOWED;
6171304f4ae32cf7121fe11e95f2a7151ea208b6ccaDianne Hackborn                }
6181304f4ae32cf7121fe11e95f2a7151ea208b6ccaDianne Hackborn            } else {
6190b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie                if (!allowMonitoring || mAppOps.checkOpNoThrow(op, mUid, mPackageName)
6200b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie                        != AppOpsManager.MODE_ALLOWED) {
6210b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie                    mAppOps.finishOp(op, mUid, mPackageName);
6220b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie                    return false;
6231304f4ae32cf7121fe11e95f2a7151ea208b6ccaDianne Hackborn                }
6241304f4ae32cf7121fe11e95f2a7151ea208b6ccaDianne Hackborn            }
6250b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie
6260b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie            return currentlyMonitoring;
6271304f4ae32cf7121fe11e95f2a7151ea208b6ccaDianne Hackborn        }
6281304f4ae32cf7121fe11e95f2a7151ea208b6ccaDianne Hackborn
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean isListener() {
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mListener != null;
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean isPendingIntent() {
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mPendingIntent != null;
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public ILocationListener getListener() {
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mListener;
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("Request for non-existent listener");
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
64748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
64848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
64948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
65048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        mListener.onStatusChanged(provider, status, extras);
651e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        // call this after broadcasting so we do not increment
652e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        // if we throw an exeption.
653e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        incrementPendingBroadcastsLocked();
65448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent statusChanged = new Intent();
66061ecb02f544d9abd098506afb50cb514818f4eb4Victoria Lease                statusChanged.putExtras(new Bundle(extras));
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
66348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
66448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
66548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
6666c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn                        mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
66737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                                getResolutionPermission(mAllowedResolutionLevel));
66848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
66948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
67048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
67148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (PendingIntent.CanceledException e) {
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean callLocationChangedLocked(Location location) {
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mListener != null) {
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
68248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
68348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
68448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
6856c5406acd72eed31f2b4e12f5eddc0e2d2a951e2Dianne Hackborn                        mListener.onLocationChanged(new Location(location));
686e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        // call this after broadcasting so we do not increment
687e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        // if we throw an exeption.
688e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        incrementPendingBroadcastsLocked();
68948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent locationChanged = new Intent();
69561ecb02f544d9abd098506afb50cb514818f4eb4Victoria Lease                locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, new Location(location));
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
69748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
69848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
69948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
7006c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn                        mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
70137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                                getResolutionPermission(mAllowedResolutionLevel));
70248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
70348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
70448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
70548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
70648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                } catch (PendingIntent.CanceledException e) {
70748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    return false;
70848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
70948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
71048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            return true;
71148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
71248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
71348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        public boolean callProviderEnabledLocked(String provider, boolean enabled) {
71415b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie            // First update AppOp monitoring.
71515b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie            // An app may get/lose location access as providers are enabled/disabled.
71615b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie            updateMonitoring(true);
71715b3191f913091e686e9e1f3708b7f8240a07e8bDavid Christie
71848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (mListener != null) {
71948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                try {
72048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
72148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
72248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
72348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        if (enabled) {
72448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            mListener.onProviderEnabled(provider);
72548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        } else {
72648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                            mListener.onProviderDisabled(provider);
72748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        }
728e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        // call this after broadcasting so we do not increment
729e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        // if we throw an exeption.
730e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly                        incrementPendingBroadcastsLocked();
73148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
73248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                } catch (RemoteException e) {
73348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    return false;
73448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                }
73548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            } else {
73648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                Intent providerIntent = new Intent();
73748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
73848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                try {
73948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    synchronized (this) {
74048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // synchronize to ensure incrementPendingBroadcastsLocked()
74148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // is called before decrementPendingBroadcasts()
7426c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn                        mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
74337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                                getResolutionPermission(mAllowedResolutionLevel));
74448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // call this after broadcasting so we do not increment
74548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        // if we throw an exeption.
74648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                        incrementPendingBroadcastsLocked();
74748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                    }
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (PendingIntent.CanceledException e) {
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return false;
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
755f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly        @Override
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void binderDied() {
7576fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (D) Log.d(TAG, "Location listener died");
7586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
7592f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            synchronized (mLock) {
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeUpdatesLocked(this);
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
76248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            synchronized (this) {
7630aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease                clearPendingBroadcastsLocked();
76448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
76548f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
76648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
767e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        @Override
76848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        public void onSendFinished(PendingIntent pendingIntent, Intent intent,
76948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood                int resultCode, String resultData, Bundle resultExtras) {
7700528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            synchronized (this) {
7710528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood                decrementPendingBroadcastsLocked();
7720528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            }
77348f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
77448f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
7750528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        // this must be called while synchronized by caller in a synchronized block
77648f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        // containing the sending of the broadcaset
77748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        private void incrementPendingBroadcastsLocked() {
77848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            if (mPendingBroadcasts++ == 0) {
7790aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease                mWakeLock.acquire();
78048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
78148f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
78248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
7830528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        private void decrementPendingBroadcastsLocked() {
7840528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            if (--mPendingBroadcasts == 0) {
7850aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease                if (mWakeLock.isHeld()) {
7860aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease                    mWakeLock.release();
7870aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease                }
7880aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease            }
7890aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease        }
7900aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease
7910aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease        public void clearPendingBroadcastsLocked() {
7920aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease            if (mPendingBroadcasts > 0) {
7930aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease                mPendingBroadcasts = 0;
7940aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease                if (mWakeLock.isHeld()) {
7950aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease                    mWakeLock.release();
7960aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease                }
79748f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood            }
79848f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood        }
79948f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    }
80048f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood
801e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
80248f17518223a2917fd82195004fbb206cb9a05a3Mike Lockwood    public void locationCallbackFinished(ILocationListener listener) {
803f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn        //Do not use getReceiverLocked here as that will add the ILocationListener to
804080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //the receiver list if it is not found.  If it is not found then the
805080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //LocationListener was removed when it had a pending broadcast and should
806080b61ba17014b8c93914f642ccbe05c76dc611dJoshua Bartel        //not be added back.
807f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn        synchronized (mLock) {
808f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn            IBinder binder = listener.asBinder();
809f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn            Receiver receiver = mReceivers.get(binder);
810f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn            if (receiver != null) {
811f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn                synchronized (receiver) {
812f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn                    // so wakelock calls will succeed
813f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn                    long identity = Binder.clearCallingIdentity();
814f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn                    receiver.decrementPendingBroadcastsLocked();
815f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn                    Binder.restoreCallingIdentity(identity);
816f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn               }
817f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn            }
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void addProviderLocked(LocationProviderInterface provider) {
82215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProviders.add(provider);
82315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProvidersByName.put(provider.getName(), provider);
82415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
82515e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
8266fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void removeProviderLocked(LocationProviderInterface provider) {
8276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        provider.disable();
82815e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProviders.remove(provider);
82915e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        mProvidersByName.remove(provider.getName());
83015e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood    }
83115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood
83203cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease    /**
83309eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease     * Returns "true" if access to the specified location provider is allowed by the current
83409eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease     * user's settings. Access to all location providers is forbidden to non-location-provider
83509eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease     * processes belonging to background users.
83603cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease     *
83703cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease     * @param provider the name of the location provider
83803cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease     * @return
83903cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease     */
84009eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease    private boolean isAllowedByCurrentUserSettingsLocked(String provider) {
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabledProviders.contains(provider)) {
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDisabledProviders.contains(provider)) {
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Use system settings
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ContentResolver resolver = mContext.getContentResolver();
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
850b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId);
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    /**
85409eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease     * Returns "true" if access to the specified location provider is allowed by the specified
85509eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease     * user's settings. Access to all location providers is forbidden to non-location-provider
85609eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease     * processes belonging to background users.
85709eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease     *
85809eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease     * @param provider the name of the location provider
85909eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease     * @param uid the requestor's UID
86009eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease     * @return
86109eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease     */
86209eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease    private boolean isAllowedByUserSettingsLocked(String provider, int uid) {
86309eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease        if (UserHandle.getUserId(uid) != mCurrentUserId && !isUidALocationProvider(uid)) {
86409eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease            return false;
86509eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease        }
86609eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease        return isAllowedByCurrentUserSettingsLocked(provider);
86709eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease    }
86809eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease
86909eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease    /**
87037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Returns the permission string associated with the specified resolution level.
87137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
87237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param resolutionLevel the resolution level
87337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @return the permission string
8746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     */
87537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private String getResolutionPermission(int resolutionLevel) {
87637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        switch (resolutionLevel) {
87737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            case RESOLUTION_LEVEL_FINE:
87837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                return android.Manifest.permission.ACCESS_FINE_LOCATION;
87937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            case RESOLUTION_LEVEL_COARSE:
88037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                return android.Manifest.permission.ACCESS_COARSE_LOCATION;
88137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            default:
88237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                return null;
8836c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn        }
884da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease    }
8856c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn
886da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease    /**
88737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Returns the resolution level allowed to the given PID/UID pair.
88837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
88937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param pid the PID
89037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param uid the UID
89137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @return resolution level allowed to the pid/uid pair
892da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease     */
89337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private int getAllowedResolutionLevel(int pid, int uid) {
89437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
89537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                pid, uid) == PackageManager.PERMISSION_GRANTED) {
89637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            return RESOLUTION_LEVEL_FINE;
89737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
89837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                pid, uid) == PackageManager.PERMISSION_GRANTED) {
89937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            return RESOLUTION_LEVEL_COARSE;
90037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        } else {
90137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            return RESOLUTION_LEVEL_NONE;
902da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease        }
9034fab68b5324e1f9b6765cdc33e66d1f074623dc2Victoria Lease    }
9044fab68b5324e1f9b6765cdc33e66d1f074623dc2Victoria Lease
9054fab68b5324e1f9b6765cdc33e66d1f074623dc2Victoria Lease    /**
90637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Returns the resolution level allowed to the caller
90737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
90837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @return resolution level allowed to caller
90937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     */
91037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private int getCallerAllowedResolutionLevel() {
91137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
91237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    }
91337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease
91437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    /**
91537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Throw SecurityException if specified resolution level is insufficient to use geofences.
91637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
91737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param allowedResolutionLevel resolution level allowed to caller
9184fab68b5324e1f9b6765cdc33e66d1f074623dc2Victoria Lease     */
91937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
92037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
9214fab68b5324e1f9b6765cdc33e66d1f074623dc2Victoria Lease            throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
9224fab68b5324e1f9b6765cdc33e66d1f074623dc2Victoria Lease        }
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
92537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    /**
92637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Return the minimum resolution level required to use the specified location provider.
92737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
92837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param provider the name of the location provider
92937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @return minimum resolution level required for provider
93037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     */
93137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private int getMinimumResolutionLevelForProviderUse(String provider) {
9328dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease        if (LocationManager.GPS_PROVIDER.equals(provider) ||
9338dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease                LocationManager.PASSIVE_PROVIDER.equals(provider)) {
9348dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease            // gps and passive providers require FINE permission
93537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            return RESOLUTION_LEVEL_FINE;
9368dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease        } else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
9378dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease                LocationManager.FUSED_PROVIDER.equals(provider)) {
9388dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease            // network and fused providers are ok with COARSE or FINE
93937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            return RESOLUTION_LEVEL_COARSE;
940941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu        } else {
941941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu            // mock providers
942941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu            LocationProviderInterface lp = mMockProviders.get(provider);
943941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu            if (lp != null) {
944941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                ProviderProperties properties = lp.getProperties();
945941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                if (properties != null) {
946941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                    if (properties.mRequiresSatellite) {
947941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                        // provider requiring satellites require FINE permission
94837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                        return RESOLUTION_LEVEL_FINE;
949941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                    } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
950941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                        // provider requiring network and or cell require COARSE or FINE
95137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                        return RESOLUTION_LEVEL_COARSE;
952941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                    }
953941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu                }
954941221c1577a34c922c03b30be7ef0a4afda4278Laurent Tu            }
9558dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease        }
95637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
957da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease    }
958da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease
95937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    /**
96037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Throw SecurityException if specified resolution level is insufficient to use the named
96137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * location provider.
96237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
96337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param allowedResolutionLevel resolution level allowed to caller
96437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param providerName the name of the location provider
96537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     */
96637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
96737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            String providerName) {
96837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
96937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        if (allowedResolutionLevel < requiredResolutionLevel) {
97037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            switch (requiredResolutionLevel) {
97137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                case RESOLUTION_LEVEL_FINE:
97237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    throw new SecurityException("\"" + providerName + "\" location provider " +
97337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                            "requires ACCESS_FINE_LOCATION permission.");
97437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                case RESOLUTION_LEVEL_COARSE:
97537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    throw new SecurityException("\"" + providerName + "\" location provider " +
97637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                            "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
97737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                default:
97837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    throw new SecurityException("Insufficient permission for \"" + providerName +
97937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                            "\" location provider.");
980da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease            }
981da479c5f8c9675dc11b3d6c4024749064d54bb67Victoria Lease        }
9828dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease    }
9838dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease
98482edc9b3482307a8e93655aadabb4f9ad24efe46David Christie    /**
98582edc9b3482307a8e93655aadabb4f9ad24efe46David Christie     * Throw SecurityException if WorkSource use is not allowed (i.e. can't blame other packages
98682edc9b3482307a8e93655aadabb4f9ad24efe46David Christie     * for battery).
98782edc9b3482307a8e93655aadabb4f9ad24efe46David Christie     */
98840e5782f5c79ea660b98b8875086f592367bc1d2David Christie    private void checkDeviceStatsAllowed() {
98982edc9b3482307a8e93655aadabb4f9ad24efe46David Christie        mContext.enforceCallingOrSelfPermission(
99082edc9b3482307a8e93655aadabb4f9ad24efe46David Christie                android.Manifest.permission.UPDATE_DEVICE_STATS, null);
99182edc9b3482307a8e93655aadabb4f9ad24efe46David Christie    }
99282edc9b3482307a8e93655aadabb4f9ad24efe46David Christie
99340e5782f5c79ea660b98b8875086f592367bc1d2David Christie    private void checkUpdateAppOpsAllowed() {
99440e5782f5c79ea660b98b8875086f592367bc1d2David Christie        mContext.enforceCallingOrSelfPermission(
99540e5782f5c79ea660b98b8875086f592367bc1d2David Christie                android.Manifest.permission.UPDATE_APP_OPS_STATS, null);
99640e5782f5c79ea660b98b8875086f592367bc1d2David Christie    }
99740e5782f5c79ea660b98b8875086f592367bc1d2David Christie
9985e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    public static int resolutionLevelToOp(int allowedResolutionLevel) {
99935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
100035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
10015e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                return AppOpsManager.OP_COARSE_LOCATION;
100235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } else {
10035e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                return AppOpsManager.OP_FINE_LOCATION;
100435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
10055e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        }
10065e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        return -1;
10075e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    }
10085e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn
10095e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    boolean reportLocationAccessNoThrow(int uid, String packageName, int allowedResolutionLevel) {
10105e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        int op = resolutionLevelToOp(allowedResolutionLevel);
10115e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        if (op >= 0) {
101235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
101335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return false;
101435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
101535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
101635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        return true;
101735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
101835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
101935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    boolean checkLocationAccess(int uid, String packageName, int allowedResolutionLevel) {
10205e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        int op = resolutionLevelToOp(allowedResolutionLevel);
10215e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        if (op >= 0) {
102235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
102335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return false;
102435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
102535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
102635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        return true;
102735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
102835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
10296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    /**
10306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * Returns all providers by name, including passive, but excluding
10310d21e2161f8542db0a54bf80b74b7fd33afef6f6Laurent Tu     * fused, also including ones that are not permitted to
10320d21e2161f8542db0a54bf80b74b7fd33afef6f6Laurent Tu     * be accessed by the calling activity or are currently disabled.
10336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     */
1034e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<String> getAllProviders() {
10366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        ArrayList<String> out;
10376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        synchronized (mLock) {
10386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            out = new ArrayList<String>(mProviders.size());
10396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (LocationProviderInterface provider : mProviders) {
10406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                String name = provider.getName();
10416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                if (LocationManager.FUSED_PROVIDER.equals(name)) {
10426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    continue;
10436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                }
10446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                out.add(name);
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10486fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "getAllProviders()=" + out);
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return out;
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    /**
10536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * Return all providers by name, that match criteria and are optionally
10546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * enabled.
10556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * Can return passive provider, but never returns fused provider.
10566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     */
1057e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
105803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
105937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
10606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        ArrayList<String> out;
106103cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease        int uid = Binder.getCallingUid();;
1062269518e83efc01b387235d6194dcf93726e384ffVictoria Lease        long identity = Binder.clearCallingIdentity();
1063b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        try {
1064b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            synchronized (mLock) {
1065b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                out = new ArrayList<String>(mProviders.size());
1066b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                for (LocationProviderInterface provider : mProviders) {
1067b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    String name = provider.getName();
1068b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    if (LocationManager.FUSED_PROVIDER.equals(name)) {
10698dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease                        continue;
10708dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease                    }
107137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
107209eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease                        if (enabledOnly && !isAllowedByUserSettingsLocked(name, uid)) {
1073b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                            continue;
1074b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        }
1075b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        if (criteria != null && !LocationProvider.propertiesMeetCriteria(
1076b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                                name, provider.getProperties(), criteria)) {
1077b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                            continue;
1078b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        }
1079b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        out.add(name);
10808dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease                    }
108103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                }
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1083b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        } finally {
1084b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            Binder.restoreCallingIdentity(identity);
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
108603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
10876fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "getProviders()=" + out);
10886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        return out;
108903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
109003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
109103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    /**
10926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * Return the name of the best provider given a Criteria object.
10936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * This method has been deprecated from the public API,
10948dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease     * and the whole LocationProvider (including #meetsCriteria)
10956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * has been deprecated as well. So this method now uses
10966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly     * some simplified logic.
109703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood     */
1098e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
109903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public String getBestProvider(Criteria criteria, boolean enabledOnly) {
11006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        String result = null;
110103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
11026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        List<String> providers = getProviders(criteria, enabledOnly);
11038dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease        if (!providers.isEmpty()) {
11046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            result = pickBest(providers);
11056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
11066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return result;
110703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
11086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        providers = getProviders(null, enabledOnly);
11098dbb63419bef8678cf92ebae1d43f549f50987c7Victoria Lease        if (!providers.isEmpty()) {
11106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            result = pickBest(providers);
11116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
11126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return result;
111303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
111403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
11156fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
11166fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        return null;
11176fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
111803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
11196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private String pickBest(List<String> providers) {
11201925e290e7ac2801311cb4e732d1bc5a5f3e0c44Victoria Lease        if (providers.contains(LocationManager.GPS_PROVIDER)) {
11216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return LocationManager.GPS_PROVIDER;
11221925e290e7ac2801311cb4e732d1bc5a5f3e0c44Victoria Lease        } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
11231925e290e7ac2801311cb4e732d1bc5a5f3e0c44Victoria Lease            return LocationManager.NETWORK_PROVIDER;
11246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else {
11256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return providers.get(0);
112603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
112703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
112803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
1129e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
113003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    public boolean providerMeetsCriteria(String provider, Criteria criteria) {
113103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
113203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        if (p == null) {
113303ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            throw new IllegalArgumentException("provider=" + provider);
113403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood        }
11356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
11366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        boolean result = LocationProvider.propertiesMeetCriteria(
11376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                p.getName(), p.getProperties(), criteria);
11386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result);
11396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        return result;
114003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood    }
114103ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void updateProvidersLocked() {
11430c5a04014d3833c9a82772a832d3bc6410fc52acBrad Fitzpatrick        boolean changesMade = false;
114415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        for (int i = mProviders.size() - 1; i >= 0; i--) {
1145d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            LocationProviderInterface p = mProviders.get(i);
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean isEnabled = p.isEnabled();
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = p.getName();
114809eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease            boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isEnabled && !shouldBeEnabled) {
1150b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                updateProviderListenersLocked(name, false, mCurrentUserId);
115175c55f92f5ca00ced05b6778389454ae50beed61David Christie                // If any provider has been disabled, clear all last locations for all providers.
115275c55f92f5ca00ced05b6778389454ae50beed61David Christie                // This is to be on the safe side in case a provider has location derived from
115375c55f92f5ca00ced05b6778389454ae50beed61David Christie                // this disabled provider.
115475c55f92f5ca00ced05b6778389454ae50beed61David Christie                mLastLocation.clear();
115575c55f92f5ca00ced05b6778389454ae50beed61David Christie                mLastLocationCoarseInterval.clear();
11560c5a04014d3833c9a82772a832d3bc6410fc52acBrad Fitzpatrick                changesMade = true;
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (!isEnabled && shouldBeEnabled) {
1158b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                updateProviderListenersLocked(name, true, mCurrentUserId);
11590c5a04014d3833c9a82772a832d3bc6410fc52acBrad Fitzpatrick                changesMade = true;
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11610c5a04014d3833c9a82772a832d3bc6410fc52acBrad Fitzpatrick        }
11620c5a04014d3833c9a82772a832d3bc6410fc52acBrad Fitzpatrick        if (changesMade) {
11635ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn            mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
11645ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn                    UserHandle.ALL);
116540a86c24d2601df4966c57573a5bf58b30a41990Tom O'Neill            mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
116640a86c24d2601df4966c57573a5bf58b30a41990Tom O'Neill                    UserHandle.ALL);
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1170b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease    private void updateProviderListenersLocked(String provider, boolean enabled, int userId) {
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int listeners = 0;
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1173d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
11746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (p == null) return;
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<Receiver> deadReceivers = null;
1177e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (records != null) {
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int N = records.size();
11816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (int i = 0; i < N; i++) {
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                UpdateRecord record = records.get(i);
1183269518e83efc01b387235d6194dcf93726e384ffVictoria Lease                if (UserHandle.getUserId(record.mReceiver.mUid) == userId) {
1184b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    // Sends a notification message to the receiver
1185b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
1186b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        if (deadReceivers == null) {
1187b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                            deadReceivers = new ArrayList<Receiver>();
1188b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        }
1189b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        deadReceivers.add(record.mReceiver);
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1191b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    listeners++;
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (deadReceivers != null) {
11976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (int i = deadReceivers.size() - 1; i >= 0; i--) {
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                removeUpdatesLocked(deadReceivers.get(i));
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1201e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (enabled) {
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.enable();
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (listeners > 0) {
12056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                applyRequirementsLocked(provider);
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.disable();
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void applyRequirementsLocked(String provider) {
12136fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        LocationProviderInterface p = mProvidersByName.get(provider);
12146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (p == null) return;
12156fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
12176fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        WorkSource worksource = new WorkSource();
12186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        ProviderRequest providerRequest = new ProviderRequest();
12196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (records != null) {
12216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (UpdateRecord record : records) {
1222269518e83efc01b387235d6194dcf93726e384ffVictoria Lease                if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
12235e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    if (checkLocationAccess(record.mReceiver.mUid, record.mReceiver.mPackageName,
12245e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            record.mReceiver.mAllowedResolutionLevel)) {
12255e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        LocationRequest locationRequest = record.mRequest;
12265e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        providerRequest.locationRequests.add(locationRequest);
12275e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        if (locationRequest.getInterval() < providerRequest.interval) {
12285e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            providerRequest.reportLocation = true;
12295e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            providerRequest.interval = locationRequest.getInterval();
12305e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        }
1231b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    }
12327e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn                }
12337e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            }
12346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
12356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (providerRequest.reportLocation) {
12366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // calculate who to blame for power
12376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // This is somewhat arbitrary. We pick a threshold interval
12386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // that is slightly higher that the minimum interval, and
12396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // spread the blame across all applications with a request
12406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // under that threshold.
12416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
12426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                for (UpdateRecord record : records) {
1243269518e83efc01b387235d6194dcf93726e384ffVictoria Lease                    if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) {
1244b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        LocationRequest locationRequest = record.mRequest;
1245b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        if (locationRequest.getInterval() <= thresholdInterval) {
1246e55c9686a180cc81e8aac1eeadad12271d8e41caDavid Christie                            if (record.mReceiver.mWorkSource != null
1247e55c9686a180cc81e8aac1eeadad12271d8e41caDavid Christie                                    && record.mReceiver.mWorkSource.size() > 0
1248e55c9686a180cc81e8aac1eeadad12271d8e41caDavid Christie                                    && record.mReceiver.mWorkSource.getName(0) != null) {
124982edc9b3482307a8e93655aadabb4f9ad24efe46David Christie                                // Assign blame to another work source.
1250e55c9686a180cc81e8aac1eeadad12271d8e41caDavid Christie                                // Can only assign blame if the WorkSource contains names.
125182edc9b3482307a8e93655aadabb4f9ad24efe46David Christie                                worksource.add(record.mReceiver.mWorkSource);
125282edc9b3482307a8e93655aadabb4f9ad24efe46David Christie                            } else {
125382edc9b3482307a8e93655aadabb4f9ad24efe46David Christie                                // Assign blame to caller.
125482edc9b3482307a8e93655aadabb4f9ad24efe46David Christie                                worksource.add(
125582edc9b3482307a8e93655aadabb4f9ad24efe46David Christie                                        record.mReceiver.mUid,
125682edc9b3482307a8e93655aadabb4f9ad24efe46David Christie                                        record.mReceiver.mPackageName);
125782edc9b3482307a8e93655aadabb4f9ad24efe46David Christie                            }
1258b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        }
12596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    }
12607e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn                }
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
12646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
12656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        p.setRequest(providerRequest, worksource);
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class UpdateRecord {
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String mProvider;
12706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final LocationRequest mRequest;
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Receiver mReceiver;
12722f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Location mLastFixBroadcast;
12732f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        long mLastStatusBroadcast;
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Note: must be constructed with lock held.
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
12786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mProvider = provider;
12806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mRequest = request;
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mReceiver = receiver;
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (records == null) {
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                records = new ArrayList<UpdateRecord>();
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRecordsByProvider.put(provider, records);
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!records.contains(this)) {
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                records.add(this);
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Method to be called when a record will no longer be used.  Calling this multiple times
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * must have the same effect as calling it once.
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
12976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        void disposeLocked(boolean removeReceiver) {
12986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // remove from mRecordsByProvider
12996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
13006fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (globalRecords != null) {
13016fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                globalRecords.remove(this);
13026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
13036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
13046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (!removeReceiver) return;  // the caller will handle the rest
13056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
13066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // remove from Receiver#mUpdateRecords
13076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
13086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (receiverRecords != null) {
13096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                receiverRecords.remove(this.mProvider);
13106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
13116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // and also remove the Receiver if it has no more update records
13126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                if (removeReceiver && receiverRecords.size() == 0) {
13136fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    removeUpdatesLocked(mReceiver);
13146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                }
13153a76fd627945c1df59aa0318867401e0e53da022Mike Lockwood            }
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
13206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            StringBuilder s = new StringBuilder();
13216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append("UpdateRecord[");
13226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append(mProvider);
13236fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append(' ').append(mReceiver.mPackageName).append('(');
13246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append(mReceiver.mUid).append(')');
13256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append(' ').append(mRequest);
13266fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            s.append(']');
13276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return s.toString();
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1331f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn    private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
133240e5782f5c79ea660b98b8875086f592367bc1d2David Christie            String packageName, WorkSource workSource, boolean hideFromAppOps) {
13332f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        IBinder binder = listener.asBinder();
13342f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver receiver = mReceivers.get(binder);
13352f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (receiver == null) {
133640e5782f5c79ea660b98b8875086f592367bc1d2David Christie            receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
133740e5782f5c79ea660b98b8875086f592367bc1d2David Christie                    hideFromAppOps);
13382f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            mReceivers.put(binder, receiver);
13392f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
13402f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            try {
13416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                receiver.getListener().asBinder().linkToDeath(receiver, 0);
13422f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            } catch (RemoteException e) {
13438a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.e(TAG, "linkToDeath failed:", e);
13442f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                return null;
13452f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            }
13462f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
13472f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        return receiver;
13482f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
13492f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
135082edc9b3482307a8e93655aadabb4f9ad24efe46David Christie    private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
135140e5782f5c79ea660b98b8875086f592367bc1d2David Christie            WorkSource workSource, boolean hideFromAppOps) {
13522f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        Receiver receiver = mReceivers.get(intent);
13532f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        if (receiver == null) {
135440e5782f5c79ea660b98b8875086f592367bc1d2David Christie            receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
135540e5782f5c79ea660b98b8875086f592367bc1d2David Christie                    hideFromAppOps);
13562f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            mReceivers.put(intent, receiver);
13572f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        }
13582f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        return receiver;
13592f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood    }
13602f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood
136137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    /**
136237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
136337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * and consistency requirements.
136437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     *
136537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @param request the LocationRequest from which to create a sanitized version
136637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @return a version of request that meets the given resolution and consistency requirements
136737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     * @hide
136837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease     */
136937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease    private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel) {
137037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        LocationRequest sanitizedRequest = new LocationRequest(request);
137137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
137237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            switch (sanitizedRequest.getQuality()) {
137309016ab4dd056a16809419d612cb865a14980880Victoria Lease                case LocationRequest.ACCURACY_FINE:
137437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
137509016ab4dd056a16809419d612cb865a14980880Victoria Lease                    break;
137609016ab4dd056a16809419d612cb865a14980880Victoria Lease                case LocationRequest.POWER_HIGH:
137737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                    sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
137809016ab4dd056a16809419d612cb865a14980880Victoria Lease                    break;
137909016ab4dd056a16809419d612cb865a14980880Victoria Lease            }
138009016ab4dd056a16809419d612cb865a14980880Victoria Lease            // throttle
138137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
138237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
138309016ab4dd056a16809419d612cb865a14980880Victoria Lease            }
138437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
138537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
138609016ab4dd056a16809419d612cb865a14980880Victoria Lease            }
138774fa7eabda3d0c1a85e0b568e3fc4230ed4fe7a4Nick Pelly        }
13884e31c4fffbc42b4c2b5dca6431cfeef9e078f5b4Nick Pelly        // make getFastestInterval() the minimum of interval and fastest interval
138937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
13904e31c4fffbc42b4c2b5dca6431cfeef9e078f5b4Nick Pelly            request.setFastestInterval(request.getInterval());
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
139237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        return sanitizedRequest;
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void checkPackageName(String packageName) {
1396e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        if (packageName == null) {
13976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            throw new SecurityException("invalid package name: " + packageName);
1398e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        }
13996fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        int uid = Binder.getCallingUid();
1400e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        String[] packages = mPackageManager.getPackagesForUid(uid);
1401e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        if (packages == null) {
1402e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly            throw new SecurityException("invalid UID " + uid);
1403e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        }
1404e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        for (String pkg : packages) {
1405e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly            if (packageName.equals(pkg)) return;
1406e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        }
14076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        throw new SecurityException("invalid package name: " + packageName);
1408e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    }
1409e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
14106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void checkPendingIntent(PendingIntent intent) {
14116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (intent == null) {
14126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            throw new IllegalArgumentException("invalid pending intent: " + intent);
14136c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn        }
14146c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn    }
14156c418d585e0a91054b168fde3130188afd006c98Dianne Hackborn
1416f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn    private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent,
141740e5782f5c79ea660b98b8875086f592367bc1d2David Christie            int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps) {
14186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (intent == null && listener == null) {
1419a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            throw new IllegalArgumentException("need either listener or intent");
14206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else if (intent != null && listener != null) {
14216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            throw new IllegalArgumentException("cannot register both listener and intent");
14226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else if (intent != null) {
14236fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            checkPendingIntent(intent);
142440e5782f5c79ea660b98b8875086f592367bc1d2David Christie            return getReceiverLocked(intent, pid, uid, packageName, workSource, hideFromAppOps);
14256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else {
142640e5782f5c79ea660b98b8875086f592367bc1d2David Christie            return getReceiverLocked(listener, pid, uid, packageName, workSource, hideFromAppOps);
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
14316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
14326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            PendingIntent intent, String packageName) {
14336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (request == null) request = DEFAULT_LOCATION_REQUEST;
14346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkPackageName(packageName);
143537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
143637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
143737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                request.getProvider());
143882edc9b3482307a8e93655aadabb4f9ad24efe46David Christie        WorkSource workSource = request.getWorkSource();
143982edc9b3482307a8e93655aadabb4f9ad24efe46David Christie        if (workSource != null && workSource.size() > 0) {
144040e5782f5c79ea660b98b8875086f592367bc1d2David Christie            checkDeviceStatsAllowed();
144140e5782f5c79ea660b98b8875086f592367bc1d2David Christie        }
144240e5782f5c79ea660b98b8875086f592367bc1d2David Christie        boolean hideFromAppOps = request.getHideFromAppOps();
144340e5782f5c79ea660b98b8875086f592367bc1d2David Christie        if (hideFromAppOps) {
144440e5782f5c79ea660b98b8875086f592367bc1d2David Christie            checkUpdateAppOpsAllowed();
144582edc9b3482307a8e93655aadabb4f9ad24efe46David Christie        }
144637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14486fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final int pid = Binder.getCallingPid();
14496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final int uid = Binder.getCallingUid();
14502b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        // providers may use public location API's, need to clear identity
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identity = Binder.clearCallingIdentity();
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1453a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            // We don't check for MODE_IGNORED here; we will do that when we go to deliver
1454a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            // a location.
145535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            checkLocationAccess(uid, packageName, allowedResolutionLevel);
1456a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
14576fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            synchronized (mLock) {
1458f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn                Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
145940e5782f5c79ea660b98b8875086f592367bc1d2David Christie                        packageName, workSource, hideFromAppOps);
146037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
14612d4d1bf14b531de9d4238b1e41b53c77f8976405Mike Lockwood            }
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(identity);
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
14686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            int pid, int uid, String packageName) {
14696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // Figure out the provider. Either its explicitly request (legacy use cases), or
14706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // use the fused provider
14716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (request == null) request = DEFAULT_LOCATION_REQUEST;
14726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        String name = request.getProvider();
147309016ab4dd056a16809419d612cb865a14980880Victoria Lease        if (name == null) {
147409016ab4dd056a16809419d612cb865a14980880Victoria Lease            throw new IllegalArgumentException("provider name must not be null");
147509016ab4dd056a16809419d612cb865a14980880Victoria Lease        }
1476c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun
1477c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun        if (D) Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
1478c5fc9988f11acc58229fb6ae80d346277318ada4Zhentao Sun                + " " + name + " " + request + " from " + packageName + "(" + uid + ")");
14796fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        LocationProviderInterface provider = mProvidersByName.get(name);
14806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (provider == null) {
1481b30f38383e4691bf23311f62649aa504832731dbVictoria Lease            throw new IllegalArgumentException("provider doesn't exist: " + name);
14826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
14836fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
14846fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        UpdateRecord record = new UpdateRecord(name, request, receiver);
14856fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
14866fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (oldRecord != null) {
14876fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            oldRecord.disposeLocked(false);
14886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
14896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
149009eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease        boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid);
14916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (isProviderEnabled) {
14926fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            applyRequirementsLocked(name);
14936fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } else {
14946fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // Notify the listener that updates are currently disabled
14956fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            receiver.callProviderEnabledLocked(name, false);
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14970b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie        // Update the monitoring here just in case multiple location requests were added to the
14980b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie        // same receiver (this request may be high power and the initial might not have been).
14990b8374501975aecd7a628336e2f7e53c272ebeeaDavid Christie        receiver.updateMonitoring(true);
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1502e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
15036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void removeUpdates(ILocationListener listener, PendingIntent intent,
15046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            String packageName) {
15056fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkPackageName(packageName);
150637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease
15076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final int pid = Binder.getCallingPid();
15086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        final int uid = Binder.getCallingUid();
15096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
1510f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn        synchronized (mLock) {
151182edc9b3482307a8e93655aadabb4f9ad24efe46David Christie            WorkSource workSource = null;
151240e5782f5c79ea660b98b8875086f592367bc1d2David Christie            boolean hideFromAppOps = false;
151340e5782f5c79ea660b98b8875086f592367bc1d2David Christie            Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid,
151440e5782f5c79ea660b98b8875086f592367bc1d2David Christie                    packageName, workSource, hideFromAppOps);
1515f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn
1516f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn            // providers may use public location API's, need to clear identity
1517f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn            long identity = Binder.clearCallingIdentity();
1518f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn            try {
15196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                removeUpdatesLocked(receiver);
1520f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn            } finally {
1521f5fdca9dc1528a7f5acec04c2f2a1b99e8f4b338Dianne Hackborn                Binder.restoreCallingIdentity(identity);
15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void removeUpdatesLocked(Receiver receiver) {
15277ff30113de68539ec840c524b8f1561f938f96c5Dianne Hackborn        if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
15306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
15316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            synchronized (receiver) {
15320aa28602d51bf41e46d18ffefe724ebc3ff7a704Victoria Lease                receiver.clearPendingBroadcastsLocked();
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15361304f4ae32cf7121fe11e95f2a7151ea208b6ccaDianne Hackborn        receiver.updateMonitoring(false);
15371304f4ae32cf7121fe11e95f2a7151ea208b6ccaDianne Hackborn
15386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // Record which providers were associated with this listener
15396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        HashSet<String> providers = new HashSet<String>();
15406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
15416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (oldRecords != null) {
15426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // Call dispose() on the obsolete update records.
15436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (UpdateRecord record : oldRecords.values()) {
15446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                record.disposeLocked(false);
15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // Accumulate providers
15476fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            providers.addAll(oldRecords.keySet());
15486fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // update provider
15516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        for (String provider : providers) {
15526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // If provider is already disabled, don't need to do anything
155309eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease            if (!isAllowedByCurrentUserSettingsLocked(provider)) {
15546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                continue;
15556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15576fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            applyRequirementsLocked(provider);
15586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
15596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1561c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    private void applyAllProviderRequirementsLocked() {
1562c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        for (LocationProviderInterface p : mProviders) {
1563c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            // If provider is already disabled, don't need to do anything
156464d41d7391e57886978e94e86cf01a167226dbfeDianne Hackborn            if (!isAllowedByCurrentUserSettingsLocked(p.getName())) {
1565c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                continue;
1566c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
1567c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
1568c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            applyRequirementsLocked(p.getName());
1569c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
1570c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    }
1571c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
15726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
15734035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly    public Location getLastLocation(LocationRequest request, String packageName) {
15746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "getLastLocation: " + request);
15756fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (request == null) request = DEFAULT_LOCATION_REQUEST;
157637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
15774035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly        checkPackageName(packageName);
157837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
157937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                request.getProvider());
158037425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        // no need to sanitize this request, as only the provider name is used
15814035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
1582a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        final int uid = Binder.getCallingUid();
1583a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        final long identity = Binder.clearCallingIdentity();
1584b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        try {
1585b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            if (mBlacklist.isBlacklisted(packageName)) {
1586b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
1587b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                        packageName);
158809016ab4dd056a16809419d612cb865a14980880Victoria Lease                return null;
158909016ab4dd056a16809419d612cb865a14980880Victoria Lease            }
1590b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease
15915e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            if (!reportLocationAccessNoThrow(uid, packageName, allowedResolutionLevel)) {
15925e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (D) Log.d(TAG, "not returning last loc for no op app: " +
15935e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        packageName);
15945e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                return null;
15955e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            }
15965e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn
1597b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            synchronized (mLock) {
1598b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                // Figure out the provider. Either its explicitly request (deprecated API's),
1599b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                // or use the fused provider
1600b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                String name = request.getProvider();
1601b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (name == null) name = LocationManager.FUSED_PROVIDER;
1602b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                LocationProviderInterface provider = mProvidersByName.get(name);
1603b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (provider == null) return null;
1604b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease
160509eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease                if (!isAllowedByUserSettingsLocked(name, uid)) return null;
1606b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease
16071b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie                Location location;
16081b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie                if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
16091b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie                    // Make sure that an app with coarse permissions can't get frequent location
16101b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie                    // updates by calling LocationManager.getLastKnownLocation repeatedly.
16111b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie                    location = mLastLocationCoarseInterval.get(name);
16121b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie                } else {
16131b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie                    location = mLastLocation.get(name);
16141b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie                }
1615b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (location == null) {
1616b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    return null;
1617b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                }
161837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
1619b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
1620b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    if (noGPSLocation != null) {
16216c5406acd72eed31f2b4e12f5eddc0e2d2a951e2Dianne Hackborn                        return new Location(mLocationFudger.getOrCreate(noGPSLocation));
1622b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                    }
162337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                } else {
16246c5406acd72eed31f2b4e12f5eddc0e2d2a951e2Dianne Hackborn                    return new Location(location);
162509016ab4dd056a16809419d612cb865a14980880Victoria Lease                }
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1627b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            return null;
1628b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        } finally {
1629b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            Binder.restoreCallingIdentity(identity);
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1633e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
16346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
16356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            String packageName) {
16366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (request == null) request = DEFAULT_LOCATION_REQUEST;
163737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
163837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
16396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkPendingIntent(intent);
16406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkPackageName(packageName);
164137425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
164237425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                request.getProvider());
164337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
16446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
164537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
16466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
16472b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        // geo-fence manager uses the public location API, need to clear identity
16482b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        int uid = Binder.getCallingUid();
164956e675b3a1c351de34de68a149762d3ad1b308c5Victoria Lease        if (UserHandle.getUserId(uid) != UserHandle.USER_OWNER) {
165056e675b3a1c351de34de68a149762d3ad1b308c5Victoria Lease            // temporary measure until geofences work for secondary users
165156e675b3a1c351de34de68a149762d3ad1b308c5Victoria Lease            Log.w(TAG, "proximity alerts are currently available only to the primary user");
165256e675b3a1c351de34de68a149762d3ad1b308c5Victoria Lease            return;
165356e675b3a1c351de34de68a149762d3ad1b308c5Victoria Lease        }
16542b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        long identity = Binder.clearCallingIdentity();
16552b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        try {
16565e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
16575e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    uid, packageName);
16582b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        } finally {
16592b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly            Binder.restoreCallingIdentity(identity);
16602b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        }
16616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
16626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
16636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
16646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
166537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForGeofenceUse(getCallerAllowedResolutionLevel());
16666fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkPendingIntent(intent);
16676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkPackageName(packageName);
16686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
16696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
16706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
16712b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        // geo-fence manager uses the public location API, need to clear identity
16722b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        long identity = Binder.clearCallingIdentity();
16732b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        try {
16742b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly            mGeofenceManager.removeFence(geofence, intent);
16752b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        } finally {
16762b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly            Binder.restoreCallingIdentity(identity);
16772b7a0d00426218523629e4e8dd2e9197d445c09bNick Pelly        }
16786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
16796fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
16806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
16816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
1682a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    public boolean addGpsStatusListener(IGpsStatusListener listener, String packageName) {
168315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood        if (mGpsStatusProvider == null) {
16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
168635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int allowedResolutionLevel = getCallerAllowedResolutionLevel();
168735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
168837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                LocationManager.GPS_PROVIDER);
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1690a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        final int uid = Binder.getCallingUid();
1691a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        final long ident = Binder.clearCallingIdentity();
1692a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        try {
16933d5173deea9d74b0476739c7108f9b77bcd8a495Victoria Lease            if (!checkLocationAccess(uid, packageName, allowedResolutionLevel)) {
1694a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                return false;
1695a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
1696a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        } finally {
1697a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            Binder.restoreCallingIdentity(ident);
1698a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
1699a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
17009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
170115e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            mGpsStatusProvider.addGpsStatusListener(listener);
17029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
17038a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "mGpsStatusProvider.addGpsStatusListener failed", e);
17049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1709e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
17109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeGpsStatusListener(IGpsStatusListener listener) {
17112f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
171215e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            try {
171315e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood                mGpsStatusProvider.removeGpsStatusListener(listener);
171415e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            } catch (Exception e) {
17158a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.e(TAG, "mGpsStatusProvider.removeGpsStatusListener failed", e);
171615e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            }
17179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1720e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
17219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean sendExtraCommand(String provider, String command, Bundle extras) {
1722c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood        if (provider == null) {
1723c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood            // throw NullPointerException to remain compatible with previous implementation
1724c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood            throw new NullPointerException();
1725c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood        }
172637425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
172737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                provider);
1728c6cc836f88349e871c2aa7579223c9220e95e5b0Mike Lockwood
17299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // and check for ACCESS_LOCATION_EXTRA_COMMANDS
1730b7e9922722f50dbf1911eb12e3ee8023c1450086Mike Lockwood        if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED)) {
17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17352f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
1736d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            LocationProviderInterface p = mProvidersByName.get(provider);
17376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (p == null) return false;
1738e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
1739d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood            return p.sendExtraCommand(command, extras);
17409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1743e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
17446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public boolean sendNiResponse(int notifId, int userResponse) {
174518ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood        if (Binder.getCallingUid() != Process.myUid()) {
174618ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood            throw new SecurityException(
174718ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood                    "calling sendNiResponse from outside of the system is not allowed");
174818ad9f657bda79069233c0b8e1476888ffd894d4Mike Lockwood        }
174922d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        try {
175022d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
17516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } catch (RemoteException e) {
17528a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
175322d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie            return false;
175422d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie        }
175522d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie    }
175622d1f9fb23015471de6af1a70e40fb5c82ecb665Danke Xie
17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1758628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood     * @return null if the provider does not exist
1759f2db9fb0f877057a9ef56908d54f3c95fc3fd552Alexey Tarasov     * @throws SecurityException if the provider is not allowed to be
17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * accessed by the caller
17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1762e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
17636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public ProviderProperties getProviderProperties(String provider) {
1764b7f9d254978b285bf04613f6e69a1afa89240ca9Laurent Tu        if (mProvidersByName.get(provider) == null) {
1765b7f9d254978b285bf04613f6e69a1afa89240ca9Laurent Tu          return null;
1766b7f9d254978b285bf04613f6e69a1afa89240ca9Laurent Tu        }
1767b7f9d254978b285bf04613f6e69a1afa89240ca9Laurent Tu
176837425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
176937425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                provider);
17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        LocationProviderInterface p;
17726fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        synchronized (mLock) {
17736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            p = mProvidersByName.get(provider);
17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (p == null) return null;
17776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        return p.getProperties();
17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1780e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isProviderEnabled(String provider) {
1782d5759437eeb3137e4a05471ff0f4681c0254e81aTom O'Neill        // TODO: remove this check in next release, see b/10696351
178337425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease        checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
178437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                provider);
1785d5759437eeb3137e4a05471ff0f4681c0254e81aTom O'Neill
1786d5759437eeb3137e4a05471ff0f4681c0254e81aTom O'Neill        // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
1787d5759437eeb3137e4a05471ff0f4681c0254e81aTom O'Neill        // so we discourage its use
17886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
17896fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
179009eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease        int uid = Binder.getCallingUid();
1791269518e83efc01b387235d6194dcf93726e384ffVictoria Lease        long identity = Binder.clearCallingIdentity();
1792b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        try {
1793b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            synchronized (mLock) {
1794b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                LocationProviderInterface p = mProvidersByName.get(provider);
1795b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (p == null) return false;
17966fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
179709eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease                return isAllowedByUserSettingsLocked(provider, uid);
1798b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            }
1799b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease        } finally {
1800b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            Binder.restoreCallingIdentity(identity);
18019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
180403cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease    /**
180503cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease     * Returns "true" if the UID belongs to a bound location provider.
180603cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease     *
180703cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease     * @param uid the uid
180803cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease     * @return true if uid belongs to a bound location provider
180903cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease     */
181003cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease    private boolean isUidALocationProvider(int uid) {
181103cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease        if (uid == Process.SYSTEM_UID) {
181203cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease            return true;
181303cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease        }
181403cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease        if (mGeocodeProvider != null) {
181503cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease            if (doesPackageHaveUid(uid, mGeocodeProvider.getConnectedPackageName())) return true;
181603cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease        }
181703cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease        for (LocationProviderProxy proxy : mProxyProviders) {
181803cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease            if (doesPackageHaveUid(uid, proxy.getConnectedPackageName())) return true;
181903cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease        }
182003cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease        return false;
182103cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease    }
182203cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease
18236fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void checkCallerIsProvider() {
1824275555c8eb3fb5df6e7320873b88b77cdde85a9eMike Lockwood        if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
18256fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                == PackageManager.PERMISSION_GRANTED) {
18262eeeec248a38ff33999c83f4b8d5bab7d50e79d2Nick Pelly            return;
18272eeeec248a38ff33999c83f4b8d5bab7d50e79d2Nick Pelly        }
18282eeeec248a38ff33999c83f4b8d5bab7d50e79d2Nick Pelly
18296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // Previously we only used the INSTALL_LOCATION_PROVIDER
18306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // check. But that is system or signature
18316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // protection level which is not flexible enough for
18326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // providers installed oustide the system image. So
18336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // also allow providers with a UID matching the
18346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // currently bound package name
18354e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood
183603cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease        if (isUidALocationProvider(Binder.getCallingUid())) {
183703cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease            return;
18386fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
183903cdd3d275499df3ef1059905899dcc5aaf2ab01Victoria Lease
18406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
18416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                "or UID of a currently bound location provider");
18429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private boolean doesPackageHaveUid(int uid, String packageName) {
18456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (packageName == null) {
18466fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return false;
18474a7b65e0d544ef1feff8e1e5789f469f89ebb85cMike Lockwood        }
18489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
18496fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            ApplicationInfo appInfo = mPackageManager.getApplicationInfo(packageName, 0);
18506fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (appInfo.uid != uid) {
18516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                return false;
18529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18536fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        } catch (NameNotFoundException e) {
18546fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return false;
18559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        return true;
18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    @Override
18606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void reportLocation(Location location, boolean passive) {
18616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        checkCallerIsProvider();
18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (!location.isComplete()) {
18646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            Log.w(TAG, "Dropping incomplete location: " + location);
18656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            return;
18669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18686fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location);
18696fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location);
18706fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        m.arg1 = (passive ? 1 : 0);
18716fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        mLocationHandler.sendMessageAtFrontOfQueue(m);
18729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18746fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
187575defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu    private static boolean shouldBroadcastSafe(
187675defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu            Location loc, Location lastLoc, UpdateRecord record, long now) {
18779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Always broadcast the first update
18789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (lastLoc == null) {
18799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
18809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1882f1be6861daea57ba0a1595739a899d05229d6d15Nick Pelly        // Check whether sufficient time has passed
18836fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        long minTime = record.mRequest.getFastestInterval();
18841b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie        long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
18851b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie                / NANOS_PER_MILLI;
18866fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
18879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
18889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Check whether sufficient distance has been traveled
18916fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        double minDistance = record.mRequest.getSmallestDisplacement();
18929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (minDistance > 0.0) {
18939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (loc.distanceTo(lastLoc) <= minDistance) {
18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
189875defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu        // Check whether sufficient number of udpates is left
189975defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu        if (record.mRequest.getNumUpdates() <= 0) {
190075defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu            return false;
190175defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu        }
190275defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu
190375defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu        // Check whether the expiry date has passed
190475defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu        if (record.mRequest.getExpireAt() < now) {
190575defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu            return false;
190675defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu        }
190775defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu
19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
19099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1911a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood    private void handleLocationChangedLocked(Location location, boolean passive) {
19124e31c4fffbc42b4c2b5dca6431cfeef9e078f5b4Nick Pelly        if (D) Log.d(TAG, "incoming location: " + location);
19134e31c4fffbc42b4c2b5dca6431cfeef9e078f5b4Nick Pelly
19146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        long now = SystemClock.elapsedRealtime();
1915a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
191760ec50a850ac7265b662df3c872583b6ef581ef8Laurent Tu        // Skip if the provider is unknown.
1918d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood        LocationProviderInterface p = mProvidersByName.get(provider);
19196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (p == null) return;
19206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
19216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // Update last known locations
192209016ab4dd056a16809419d612cb865a14980880Victoria Lease        Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
192309016ab4dd056a16809419d612cb865a14980880Victoria Lease        Location lastNoGPSLocation = null;
19246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        Location lastLocation = mLastLocation.get(provider);
19254e50b78bda9cd58be61581d2886c88ff6348a1c1Mike Lockwood        if (lastLocation == null) {
19266fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            lastLocation = new Location(provider);
19276fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mLastLocation.put(provider, lastLocation);
192809016ab4dd056a16809419d612cb865a14980880Victoria Lease        } else {
192909016ab4dd056a16809419d612cb865a14980880Victoria Lease            lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
193009016ab4dd056a16809419d612cb865a14980880Victoria Lease            if (noGPSLocation == null && lastNoGPSLocation != null) {
193109016ab4dd056a16809419d612cb865a14980880Victoria Lease                // New location has no no-GPS location: adopt last no-GPS location. This is set
193209016ab4dd056a16809419d612cb865a14980880Victoria Lease                // directly into location because we do not want to notify COARSE clients.
193309016ab4dd056a16809419d612cb865a14980880Victoria Lease                location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
193409016ab4dd056a16809419d612cb865a14980880Victoria Lease            }
19359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19366fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        lastLocation.set(location);
19379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19381b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie        // Update last known coarse interval location if enough time has passed.
19391b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie        Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
19401b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie        if (lastLocationCoarseInterval == null) {
19411b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie            lastLocationCoarseInterval = new Location(location);
19421b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie            mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval);
19431b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie        }
19441b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie        long timeDiffNanos = location.getElapsedRealtimeNanos()
19451b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie                - lastLocationCoarseInterval.getElapsedRealtimeNanos();
19461b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie        if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
19471b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie            lastLocationCoarseInterval.set(location);
19481b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie        }
19491b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie        // Don't ever return a coarse location that is more recent than the allowed update
19501b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie        // interval (i.e. don't allow an app to keep registering and unregistering for
19511b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie        // location updates to overcome the minimum interval).
19521b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie        noGPSLocation =
19531b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie                lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
19541b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie
195560ec50a850ac7265b662df3c872583b6ef581ef8Laurent Tu        // Skip if there are no UpdateRecords for this provider.
195660ec50a850ac7265b662df3c872583b6ef581ef8Laurent Tu        ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
195760ec50a850ac7265b662df3c872583b6ef581ef8Laurent Tu        if (records == null || records.size() == 0) return;
195860ec50a850ac7265b662df3c872583b6ef581ef8Laurent Tu
195909016ab4dd056a16809419d612cb865a14980880Victoria Lease        // Fetch coarse location
196009016ab4dd056a16809419d612cb865a14980880Victoria Lease        Location coarseLocation = null;
19611b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie        if (noGPSLocation != null) {
196209016ab4dd056a16809419d612cb865a14980880Victoria Lease            coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
196309016ab4dd056a16809419d612cb865a14980880Victoria Lease        }
196409016ab4dd056a16809419d612cb865a14980880Victoria Lease
19659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Fetch latest status update time
19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long newStatusUpdateTime = p.getStatusUpdateTime();
19679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19687ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood       // Get latest status
19699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bundle extras = new Bundle();
19709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int status = p.getStatus(extras);
19719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<Receiver> deadReceivers = null;
19736fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        ArrayList<UpdateRecord> deadUpdateRecords = null;
1974e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
19759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Broadcast location or status to all listeners
19766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        for (UpdateRecord r : records) {
19779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Receiver receiver = r.mReceiver;
197803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            boolean receiverDead = false;
19794035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
1980269518e83efc01b387235d6194dcf93726e384ffVictoria Lease            int receiverUserId = UserHandle.getUserId(receiver.mUid);
19812f5b97c518f6b6ab89e19d3a335c148400f03268Victoria Lease            if (receiverUserId != mCurrentUserId && !isUidALocationProvider(receiver.mUid)) {
1982b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                if (D) {
1983269518e83efc01b387235d6194dcf93726e384ffVictoria Lease                    Log.d(TAG, "skipping loc update for background user " + receiverUserId +
1984b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                            " (current user: " + mCurrentUserId + ", app: " +
1985b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                            receiver.mPackageName + ")");
1986b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                }
1987b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease                continue;
1988b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease            }
1989b711d57ca4e2c6a1befbfa1a41f4b8094755a93fVictoria Lease
19904035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            if (mBlacklist.isBlacklisted(receiver.mPackageName)) {
19914035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
19924035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                        receiver.mPackageName);
19934035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly                continue;
19944035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            }
19954035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly
19965e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            if (!reportLocationAccessNoThrow(receiver.mUid, receiver.mPackageName,
19975e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    receiver.mAllowedResolutionLevel)) {
19985e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (D) Log.d(TAG, "skipping loc update for no op app: " +
19995e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        receiver.mPackageName);
20005e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                continue;
20015e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            }
20025e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn
200309016ab4dd056a16809419d612cb865a14980880Victoria Lease            Location notifyLocation = null;
200437425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease            if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
200537425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                notifyLocation = coarseLocation;  // use coarse location
20066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            } else {
200737425c3475877f2fdadb78f669ec57fecf82dca7Victoria Lease                notifyLocation = lastLocation;  // use fine location
20086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
200909016ab4dd056a16809419d612cb865a14980880Victoria Lease            if (notifyLocation != null) {
201009016ab4dd056a16809419d612cb865a14980880Victoria Lease                Location lastLoc = r.mLastFixBroadcast;
201175defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu                if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) {
201209016ab4dd056a16809419d612cb865a14980880Victoria Lease                    if (lastLoc == null) {
201309016ab4dd056a16809419d612cb865a14980880Victoria Lease                        lastLoc = new Location(notifyLocation);
201409016ab4dd056a16809419d612cb865a14980880Victoria Lease                        r.mLastFixBroadcast = lastLoc;
201509016ab4dd056a16809419d612cb865a14980880Victoria Lease                    } else {
201609016ab4dd056a16809419d612cb865a14980880Victoria Lease                        lastLoc.set(notifyLocation);
201709016ab4dd056a16809419d612cb865a14980880Victoria Lease                    }
201809016ab4dd056a16809419d612cb865a14980880Victoria Lease                    if (!receiver.callLocationChangedLocked(notifyLocation)) {
201909016ab4dd056a16809419d612cb865a14980880Victoria Lease                        Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
202009016ab4dd056a16809419d612cb865a14980880Victoria Lease                        receiverDead = true;
202109016ab4dd056a16809419d612cb865a14980880Victoria Lease                    }
202275defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu                    r.mRequest.decrementNumUpdates();
20239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
20249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20262f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood            long prevStatusUpdateTime = r.mLastStatusBroadcast;
20279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((newStatusUpdateTime > prevStatusUpdateTime) &&
202809016ab4dd056a16809419d612cb865a14980880Victoria Lease                    (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
20299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20302f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood                r.mLastStatusBroadcast = newStatusUpdateTime;
20319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!receiver.callStatusChangedLocked(provider, status, extras)) {
203203ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    receiverDead = true;
20338a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
203403ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                }
203503ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood            }
203603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood
20376fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // track expired records
203875defb6f8840dcd2aaf866a5df9d689413fbe433Laurent Tu            if (r.mRequest.getNumUpdates() <= 0 || r.mRequest.getExpireAt() < now) {
20396fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                if (deadUpdateRecords == null) {
20406fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    deadUpdateRecords = new ArrayList<UpdateRecord>();
20416fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                }
20426fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                deadUpdateRecords.add(r);
20436fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
20446fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // track dead receivers
20456fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (receiverDead) {
204603ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                if (deadReceivers == null) {
204703ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    deadReceivers = new ArrayList<Receiver>();
204803ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                }
204903ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                if (!deadReceivers.contains(receiver)) {
205003ca216ac19ea4e7afcb183c20c7c780f0d97756Mike Lockwood                    deadReceivers.add(receiver);
20519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
20529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2054e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
20556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        // remove dead records and receivers outside the loop
20569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (deadReceivers != null) {
20576fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (Receiver receiver : deadReceivers) {
20586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                removeUpdatesLocked(receiver);
20596fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
20606fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
20616fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        if (deadUpdateRecords != null) {
20626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (UpdateRecord r : deadUpdateRecords) {
20636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                r.disposeLocked(true);
20649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20658b38b29b5213c429d1e9802d02549b5638f40706Victoria Lease            applyRequirementsLocked(provider);
20668b38b29b5213c429d1e9802d02549b5638f40706Victoria Lease        }
20679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class LocationWorkerHandler extends Handler {
20705cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease        public LocationWorkerHandler(Looper looper) {
20715cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease            super(looper, null, true);
20725cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease        }
20735cd731a2333479d85b1bdf6dbf8a185df2877146Victoria Lease
20749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
20759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void handleMessage(Message msg) {
20766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            switch (msg.what) {
20776fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                case MSG_LOCATION_CHANGED:
20786fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    handleLocationChanged((Location) msg.obj, msg.arg1 == 1);
20796fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    break;
20806fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
20816fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        }
20826fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    }
208398cb66797422c4ccdee6f1a07636146d784a471bMike Lockwood
208454ca7aef2e12b240caa6fb1a1e65abd234bea337Victoria Lease    private boolean isMockProvider(String provider) {
208554ca7aef2e12b240caa6fb1a1e65abd234bea337Victoria Lease        synchronized (mLock) {
208654ca7aef2e12b240caa6fb1a1e65abd234bea337Victoria Lease            return mMockProviders.containsKey(provider);
208754ca7aef2e12b240caa6fb1a1e65abd234bea337Victoria Lease        }
208854ca7aef2e12b240caa6fb1a1e65abd234bea337Victoria Lease    }
208954ca7aef2e12b240caa6fb1a1e65abd234bea337Victoria Lease
20906fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private void handleLocationChanged(Location location, boolean passive) {
209154ca7aef2e12b240caa6fb1a1e65abd234bea337Victoria Lease        // create a working copy of the incoming Location so that the service can modify it without
209254ca7aef2e12b240caa6fb1a1e65abd234bea337Victoria Lease        // disturbing the caller's copy
209354ca7aef2e12b240caa6fb1a1e65abd234bea337Victoria Lease        Location myLocation = new Location(location);
209454ca7aef2e12b240caa6fb1a1e65abd234bea337Victoria Lease        String provider = myLocation.getProvider();
209554ca7aef2e12b240caa6fb1a1e65abd234bea337Victoria Lease
209654ca7aef2e12b240caa6fb1a1e65abd234bea337Victoria Lease        // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this
209754ca7aef2e12b240caa6fb1a1e65abd234bea337Victoria Lease        // bit if location did not come from a mock provider because passive/fused providers can
209854ca7aef2e12b240caa6fb1a1e65abd234bea337Victoria Lease        // forward locations from mock providers, and should not grant them legitimacy in doing so.
209954ca7aef2e12b240caa6fb1a1e65abd234bea337Victoria Lease        if (!myLocation.isFromMockProvider() && isMockProvider(provider)) {
210054ca7aef2e12b240caa6fb1a1e65abd234bea337Victoria Lease            myLocation.setIsFromMockProvider(true);
210154ca7aef2e12b240caa6fb1a1e65abd234bea337Victoria Lease        }
21026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
21036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        synchronized (mLock) {
210409eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease            if (isAllowedByCurrentUserSettingsLocked(provider)) {
210509eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease                if (!passive) {
210609eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease                    // notify passive provider of the new location
210709eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease                    mPassiveProvider.updateLocation(myLocation);
210809eeaecf7440ff63c937337bb2f50079ebbbf9a2Victoria Lease                }
210954ca7aef2e12b240caa6fb1a1e65abd234bea337Victoria Lease                handleLocationChangedLocked(myLocation, passive);
21109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
21119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21146fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    private final PackageMonitor mPackageMonitor = new PackageMonitor() {
21150528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood        @Override
21166fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly        public void onPackageDisappeared(String packageName, int reason) {
21176fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // remove all receivers associated with this package name
21186fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            synchronized (mLock) {
21196fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                ArrayList<Receiver> deadReceivers = null;
21206fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
21216fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                for (Receiver receiver : mReceivers.values()) {
21226fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    if (receiver.mPackageName.equals(packageName)) {
21236fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                        if (deadReceivers == null) {
21246fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                            deadReceivers = new ArrayList<Receiver>();
21259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
21266fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                        deadReceivers.add(receiver);
21279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
21289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
21299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                // perform removal outside of mReceivers loop
21316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                if (deadReceivers != null) {
21326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    for (Receiver receiver : deadReceivers) {
21336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                        removeUpdatesLocked(receiver);
21349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
21359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
21369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
21379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21380528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood    };
21399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Geocoder
21419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2142e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
2143e15735a9e0c0b1448b68f2d6b3247404fc1df417Mike Lockwood    public boolean geocoderIsPresent() {
214401ac80b715881db22bde8b31633dd8a4dc375389Mark Vandevoorde        return mGeocodeProvider != null;
214501ac80b715881db22bde8b31633dd8a4dc375389Mark Vandevoorde    }
214601ac80b715881db22bde8b31633dd8a4dc375389Mark Vandevoorde
2147e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
21489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String getFromLocation(double latitude, double longitude, int maxResults,
214934901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwood            GeocoderParams params, List<Address> addrs) {
2150a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        if (mGeocodeProvider != null) {
2151628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood            return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
2152628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                    params, addrs);
21539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2154a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        return null;
21559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2157a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood
2158e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
21599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String getFromLocationName(String locationName,
2160a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            double lowerLeftLatitude, double lowerLeftLongitude,
2161a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood            double upperRightLatitude, double upperRightLongitude, int maxResults,
216234901409a404c8c66914c5a8ad0f29b1bcde0e78Mike Lockwood            GeocoderParams params, List<Address> addrs) {
2163a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood
2164a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        if (mGeocodeProvider != null) {
2165628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood            return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
2166628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                    lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
2167628fd6d9c11ed9806abebf34bc986247c106328fMike Lockwood                    maxResults, params, addrs);
21689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2169a55c321329ae52a2db7a4f2bd36673a20b8f271dMike Lockwood        return null;
21709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Mock Providers
21739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void checkMockPermissionsSafe() {
21759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(),
21769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1;
21779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!allowMocks) {
21789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting");
21799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) !=
21829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            PackageManager.PERMISSION_GRANTED) {
21839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission");
2184e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly        }
21859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2187e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
21886fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly    public void addTestProvider(String name, ProviderProperties properties) {
21899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
21909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2191a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
2192a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood            throw new IllegalArgumentException("Cannot mock the passive location provider");
2193a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood        }
2194a4903f254b4711c8fc0ac5f7e3d605f4dce34f35Mike Lockwood
219586328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood        long identity = Binder.clearCallingIdentity();
21962f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
21976fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            MockProvider provider = new MockProvider(name, this, properties);
21987566c1debebe072af76411e11d96810fd1409482Mike Lockwood            // remove the real provider if we are replacing GPS or network provider
21997566c1debebe072af76411e11d96810fd1409482Mike Lockwood            if (LocationManager.GPS_PROVIDER.equals(name)
22001332b53522e281012fefb34bfbcc68a03028f516Nick Pelly                    || LocationManager.NETWORK_PROVIDER.equals(name)
22011332b53522e281012fefb34bfbcc68a03028f516Nick Pelly                    || LocationManager.FUSED_PROVIDER.equals(name)) {
2202d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                LocationProviderInterface p = mProvidersByName.get(name);
2203d03ff94fe58045b5bd1dd783fb98026778a4265dMike Lockwood                if (p != null) {
22046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    removeProviderLocked(p);
22057566c1debebe072af76411e11d96810fd1409482Mike Lockwood                }
22067566c1debebe072af76411e11d96810fd1409482Mike Lockwood            }
220715e3d0f082d551f8819fbe4b0d502cc108627876Mike Lockwood            if (mProvidersByName.get(name) != null) {
22089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
22099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
22106fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            addProviderLocked(provider);
22117ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mMockProviders.put(name, provider);
22126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mLastLocation.put(name, null);
22131b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie            mLastLocationCoarseInterval.put(name, null);
22149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
22159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
221686328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood        Binder.restoreCallingIdentity(identity);
22179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2219e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
22209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeTestProvider(String provider) {
22219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
22222f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
2223a6d0b6f8518c7ee110c907166d53a8d46ead97f1You Kim            MockProvider mockProvider = mMockProviders.remove(provider);
22247ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
22259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
22269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
222786328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            long identity = Binder.clearCallingIdentity();
22286fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            removeProviderLocked(mProvidersByName.get(provider));
22296fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
22306fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            // reinstate real provider if available
22316fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            LocationProviderInterface realProvider = mRealProviders.get(provider);
22326fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (realProvider != null) {
22336fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                addProviderLocked(realProvider);
22346fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
22356fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            mLastLocation.put(provider, null);
22361b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie            mLastLocationCoarseInterval.put(provider, null);
22379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
223886328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            Binder.restoreCallingIdentity(identity);
22399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2242e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
22439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderLocation(String provider, Location loc) {
22449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
22452f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
22467ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
22477ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
22489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
22499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
225095427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
225195427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            long identity = Binder.clearCallingIdentity();
22527ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.setLocation(loc);
225395427cdbd802f7cb529d62bb79953c45b36a8fcfMike Lockwood            Binder.restoreCallingIdentity(identity);
22549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2257e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
22589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderLocation(String provider) {
22599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
22602f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
22617ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
22627ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
22639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
22649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
22657ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.clearLocation();
22669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2269e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
22709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderEnabled(String provider, boolean enabled) {
22719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
22722f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
22737ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
22747ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
22759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
22769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
227786328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            long identity = Binder.clearCallingIdentity();
22789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (enabled) {
22797ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                mockProvider.enable();
22809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEnabledProviders.add(provider);
22819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDisabledProviders.remove(provider);
22829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
22837ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                mockProvider.disable();
22849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mEnabledProviders.remove(provider);
22859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDisabledProviders.add(provider);
22869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
22879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
228886328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            Binder.restoreCallingIdentity(identity);
22899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2292e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
22939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderEnabled(String provider) {
22949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
22952f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
22967ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
22977ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
22989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
22999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
230086328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            long identity = Binder.clearCallingIdentity();
23019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEnabledProviders.remove(provider);
23029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDisabledProviders.remove(provider);
23039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateProvidersLocked();
230486328a99bd55532e318441d48ee9eb96cdc42403Mike Lockwood            Binder.restoreCallingIdentity(identity);
23059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
23079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2308e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
23099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
23109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
23112f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
23127ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
23137ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
23149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
23159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23167ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.setStatus(status, extras, updateTime);
23179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
23199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2320e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
23219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearTestProviderStatus(String provider) {
23229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkMockPermissionsSafe();
23232f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
23247ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            MockProvider mockProvider = mMockProviders.get(provider);
23257ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            if (mockProvider == null) {
23269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
23279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23287ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood            mockProvider.clearStatus();
23299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
23319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void log(String log) {
23339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Log.isLoggable(TAG, Log.VERBOSE)) {
23348a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.d(TAG, log);
23359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2337e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
2338e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly    @Override
23399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
23409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
23419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
23420528b9b26a9d64ba43acd0e334638303d514b8ebMike Lockwood            pw.println("Permission Denial: can't dump LocationManagerService from from pid="
23439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Binder.getCallingPid()
23449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", uid=" + Binder.getCallingUid());
23459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
23469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2347e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
23482f82c4eb0b4d315481ad79725ad6f52c5ec69685Mike Lockwood        synchronized (mLock) {
23499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("Current Location Manager state:");
23509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Location Listeners:");
23516fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (Receiver receiver : mReceivers.values()) {
23526fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                pw.println("    " + receiver);
23539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Records by Provider:");
23556fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
23566fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                pw.println("    " + entry.getKey() + ":");
23576fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                for (UpdateRecord record : entry.getValue()) {
23586fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    pw.println("      " + record);
23599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
23609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("  Last Known Locations:");
23626fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
23636fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                String provider = entry.getKey();
23646fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                Location location = entry.getValue();
23656fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                pw.println("    " + provider + ": " + location);
23669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23676fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
23681b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie            pw.println("  Last Known Locations Coarse Intervals:");
23691b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie            for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
23701b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie                String provider = entry.getKey();
23711b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie                Location location = entry.getValue();
23721b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie                pw.println("    " + provider + ": " + location);
23731b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie            }
23741b9b7b1f1b4479cc1c7003c75f9c05dfba8c56acDavid Christie
2375e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly            mGeofenceManager.dump(pw);
23766fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
23779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mEnabledProviders.size() > 0) {
23789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Enabled Providers:");
23799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (String i : mEnabledProviders) {
23809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i);
23819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2382e0fd693c6098f59004f9e96ad75c058e26c337b0Nick Pelly
23839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mDisabledProviders.size() > 0) {
23859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Disabled Providers:");
23869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (String i : mDisabledProviders) {
23879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pw.println("    " + i);
23889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
23899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23904035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            pw.append("  ");
23914035f5a7c191a68bc9a5912ce44c43c82e9e5dbfNick Pelly            mBlacklist.dump(pw);
23929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mMockProviders.size() > 0) {
23939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pw.println("  Mock Providers:");
23949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
23957ec434e2e179776d75c8a4da66dcfd2ee630c5d8Mike Lockwood                    i.getValue().dump(pw, "      ");
23969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
23979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23986fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly
239974fa7eabda3d0c1a85e0b568e3fc4230ed4fe7a4Nick Pelly            pw.append("  fudger: ");
240074fa7eabda3d0c1a85e0b568e3fc4230ed4fe7a4Nick Pelly            mLocationFudger.dump(fd, pw,  args);
240174fa7eabda3d0c1a85e0b568e3fc4230ed4fe7a4Nick Pelly
24026fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            if (args.length > 0 && "short".equals(args[0])) {
24036fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                return;
24046fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly            }
24053c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger            for (LocationProviderInterface provider: mProviders) {
24066fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                pw.print(provider.getName() + " Internal State");
24076fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                if (provider instanceof LocationProviderProxy) {
24086fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    LocationProviderProxy proxy = (LocationProviderProxy) provider;
24096fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                    pw.print(" (" + proxy.getConnectedPackageName() + ")");
24103c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger                }
24116fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                pw.println(":");
24126fa9ad4afcd762aea519ff61811386c23d18ddb2Nick Pelly                provider.dump(fd, pw, args);
24133c8fbdf5dd19fad0b3006557716ee1026d7d5899Fred Fettinger            }
24149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
24159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
24169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2417