Home | History | Annotate | Download | only in location
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.location;
     18 
     19 import android.app.PendingIntent;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.os.Bundle;
     23 import android.os.Looper;
     24 import android.os.RemoteException;
     25 import android.os.Handler;
     26 import android.os.Message;
     27 import android.util.Log;
     28 
     29 import com.android.internal.location.DummyLocationProvider;
     30 
     31 import java.util.ArrayList;
     32 import java.util.HashMap;
     33 import java.util.List;
     34 
     35 /**
     36  * This class provides access to the system location services.  These
     37  * services allow applications to obtain periodic updates of the
     38  * device's geographical location, or to fire an application-specified
     39  * {@link Intent} when the device enters the proximity of a given
     40  * geographical location.
     41  *
     42  * <p>You do not
     43  * instantiate this class directly; instead, retrieve it through
     44  * {@link android.content.Context#getSystemService
     45  * Context.getSystemService(Context.LOCATION_SERVICE)}.
     46  *
     47  * <div class="special reference">
     48  * <h3>Developer Guides</h3>
     49  * <p>For more information about using location services, read the
     50  * <a href="{@docRoot}guide/topics/location/index.html">Location and Maps</a>
     51  * developer guide.</p>
     52  * </div>
     53  */
     54 public class LocationManager {
     55     private static final String TAG = "LocationManager";
     56     private ILocationManager mService;
     57     private final HashMap<GpsStatus.Listener, GpsStatusListenerTransport> mGpsStatusListeners =
     58             new HashMap<GpsStatus.Listener, GpsStatusListenerTransport>();
     59     private final HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport> mNmeaListeners =
     60             new HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport>();
     61     private final GpsStatus mGpsStatus = new GpsStatus();
     62 
     63     /**
     64      * Name of the network location provider.  This provider determines location based on
     65      * availability of cell tower and WiFi access points. Results are retrieved
     66      * by means of a network lookup.
     67      *
     68      * Requires either of the permissions android.permission.ACCESS_COARSE_LOCATION
     69      * or android.permission.ACCESS_FINE_LOCATION.
     70      */
     71     public static final String NETWORK_PROVIDER = "network";
     72 
     73     /**
     74      * Name of the GPS location provider. This provider determines location using
     75      * satellites. Depending on conditions, this provider may take a while to return
     76      * a location fix.
     77      *
     78      * Requires the permission android.permission.ACCESS_FINE_LOCATION.
     79      *
     80      * <p> The extras Bundle for the GPS location provider can contain the
     81      * following key/value pairs:
     82      *
     83      * <ul>
     84      * <li> satellites - the number of satellites used to derive the fix
     85      * </ul>
     86      */
     87     public static final String GPS_PROVIDER = "gps";
     88 
     89     /**
     90      * A special location provider for receiving locations without actually initiating
     91      * a location fix. This provider can be used to passively receive location updates
     92      * when other applications or services request them without actually requesting
     93      * the locations yourself.  This provider will return locations generated by other
     94      * providers.  You can query the {@link Location#getProvider()} method to determine
     95      * the origin of the location update.
     96      *
     97      * Requires the permission android.permission.ACCESS_FINE_LOCATION, although if the GPS
     98      * is not enabled this provider might only return coarse fixes.
     99      */
    100     public static final String PASSIVE_PROVIDER = "passive";
    101 
    102     /**
    103      * Key used for the Bundle extra holding a boolean indicating whether
    104      * a proximity alert is entering (true) or exiting (false)..
    105      */
    106     public static final String KEY_PROXIMITY_ENTERING = "entering";
    107 
    108     /**
    109      * Key used for a Bundle extra holding an Integer status value
    110      * when a status change is broadcast using a PendingIntent.
    111      */
    112     public static final String KEY_STATUS_CHANGED = "status";
    113 
    114     /**
    115      * Key used for a Bundle extra holding an Boolean status value
    116      * when a provider enabled/disabled event is broadcast using a PendingIntent.
    117      */
    118     public static final String KEY_PROVIDER_ENABLED = "providerEnabled";
    119 
    120     /**
    121      * Key used for a Bundle extra holding a Location value
    122      * when a location change is broadcast using a PendingIntent.
    123      */
    124     public static final String KEY_LOCATION_CHANGED = "location";
    125 
    126     /**
    127      * Broadcast intent action indicating that the GPS has either been
    128      * enabled or disabled. An intent extra provides this state as a boolean,
    129      * where {@code true} means enabled.
    130      * @see #EXTRA_GPS_ENABLED
    131      *
    132      * {@hide}
    133      */
    134     public static final String GPS_ENABLED_CHANGE_ACTION =
    135         "android.location.GPS_ENABLED_CHANGE";
    136 
    137     /**
    138      * Broadcast intent action when the configured location providers
    139      * change.
    140      */
    141     public static final String PROVIDERS_CHANGED_ACTION =
    142         "android.location.PROVIDERS_CHANGED";
    143 
    144     /**
    145      * Broadcast intent action indicating that the GPS has either started or
    146      * stopped receiving GPS fixes. An intent extra provides this state as a
    147      * boolean, where {@code true} means that the GPS is actively receiving fixes.
    148      * @see #EXTRA_GPS_ENABLED
    149      *
    150      * {@hide}
    151      */
    152     public static final String GPS_FIX_CHANGE_ACTION =
    153         "android.location.GPS_FIX_CHANGE";
    154 
    155     /**
    156      * The lookup key for a boolean that indicates whether GPS is enabled or
    157      * disabled. {@code true} means GPS is enabled. Retrieve it with
    158      * {@link android.content.Intent#getBooleanExtra(String,boolean)}.
    159      *
    160      * {@hide}
    161      */
    162     public static final String EXTRA_GPS_ENABLED = "enabled";
    163 
    164     private final Context mContext;
    165 
    166     // Map from LocationListeners to their associated ListenerTransport objects
    167     private HashMap<LocationListener,ListenerTransport> mListeners =
    168         new HashMap<LocationListener,ListenerTransport>();
    169 
    170     private class ListenerTransport extends ILocationListener.Stub {
    171         private static final int TYPE_LOCATION_CHANGED = 1;
    172         private static final int TYPE_STATUS_CHANGED = 2;
    173         private static final int TYPE_PROVIDER_ENABLED = 3;
    174         private static final int TYPE_PROVIDER_DISABLED = 4;
    175 
    176         private LocationListener mListener;
    177         private final Handler mListenerHandler;
    178 
    179         ListenerTransport(LocationListener listener, Looper looper) {
    180             mListener = listener;
    181 
    182             if (looper == null) {
    183                 mListenerHandler = new Handler() {
    184                     @Override
    185                     public void handleMessage(Message msg) {
    186                         _handleMessage(msg);
    187                     }
    188                 };
    189             } else {
    190                 mListenerHandler = new Handler(looper) {
    191                     @Override
    192                     public void handleMessage(Message msg) {
    193                         _handleMessage(msg);
    194                     }
    195                 };
    196             }
    197         }
    198 
    199         public void onLocationChanged(Location location) {
    200             Message msg = Message.obtain();
    201             msg.what = TYPE_LOCATION_CHANGED;
    202             msg.obj = location;
    203             mListenerHandler.sendMessage(msg);
    204         }
    205 
    206         public void onStatusChanged(String provider, int status, Bundle extras) {
    207             Message msg = Message.obtain();
    208             msg.what = TYPE_STATUS_CHANGED;
    209             Bundle b = new Bundle();
    210             b.putString("provider", provider);
    211             b.putInt("status", status);
    212             if (extras != null) {
    213                 b.putBundle("extras", extras);
    214             }
    215             msg.obj = b;
    216             mListenerHandler.sendMessage(msg);
    217         }
    218 
    219         public void onProviderEnabled(String provider) {
    220             Message msg = Message.obtain();
    221             msg.what = TYPE_PROVIDER_ENABLED;
    222             msg.obj = provider;
    223             mListenerHandler.sendMessage(msg);
    224         }
    225 
    226         public void onProviderDisabled(String provider) {
    227             Message msg = Message.obtain();
    228             msg.what = TYPE_PROVIDER_DISABLED;
    229             msg.obj = provider;
    230             mListenerHandler.sendMessage(msg);
    231         }
    232 
    233         private void _handleMessage(Message msg) {
    234             switch (msg.what) {
    235                 case TYPE_LOCATION_CHANGED:
    236                     Location location = new Location((Location) msg.obj);
    237                     mListener.onLocationChanged(location);
    238                     break;
    239                 case TYPE_STATUS_CHANGED:
    240                     Bundle b = (Bundle) msg.obj;
    241                     String provider = b.getString("provider");
    242                     int status = b.getInt("status");
    243                     Bundle extras = b.getBundle("extras");
    244                     mListener.onStatusChanged(provider, status, extras);
    245                     break;
    246                 case TYPE_PROVIDER_ENABLED:
    247                     mListener.onProviderEnabled((String) msg.obj);
    248                     break;
    249                 case TYPE_PROVIDER_DISABLED:
    250                     mListener.onProviderDisabled((String) msg.obj);
    251                     break;
    252             }
    253             try {
    254                 mService.locationCallbackFinished(this);
    255             } catch (RemoteException e) {
    256                 Log.e(TAG, "locationCallbackFinished: RemoteException", e);
    257             }
    258         }
    259     }
    260     /**
    261      * @hide - hide this constructor because it has a parameter
    262      * of type ILocationManager, which is a system private class. The
    263      * right way to create an instance of this class is using the
    264      * factory Context.getSystemService.
    265      */
    266     public LocationManager(Context context, ILocationManager service) {
    267         mService = service;
    268         mContext = context;
    269     }
    270 
    271     private LocationProvider createProvider(String name, Bundle info) {
    272         DummyLocationProvider provider =
    273             new DummyLocationProvider(name, mService);
    274         provider.setRequiresNetwork(info.getBoolean("network"));
    275         provider.setRequiresSatellite(info.getBoolean("satellite"));
    276         provider.setRequiresCell(info.getBoolean("cell"));
    277         provider.setHasMonetaryCost(info.getBoolean("cost"));
    278         provider.setSupportsAltitude(info.getBoolean("altitude"));
    279         provider.setSupportsSpeed(info.getBoolean("speed"));
    280         provider.setSupportsBearing(info.getBoolean("bearing"));
    281         provider.setPowerRequirement(info.getInt("power"));
    282         provider.setAccuracy(info.getInt("accuracy"));
    283         return provider;
    284     }
    285 
    286     /**
    287      * Returns a list of the names of all known location providers.  All
    288      * providers are returned, including ones that are not permitted to be
    289      * accessed by the calling activity or are currently disabled.
    290      *
    291      * @return list of Strings containing names of the providers
    292      */
    293     public List<String> getAllProviders() {
    294         if (false) {
    295             Log.d(TAG, "getAllProviders");
    296         }
    297         try {
    298             return mService.getAllProviders();
    299         } catch (RemoteException ex) {
    300             Log.e(TAG, "getAllProviders: RemoteException", ex);
    301         }
    302         return null;
    303     }
    304 
    305     /**
    306      * Returns a list of the names of location providers.  Only providers that
    307      * are permitted to be accessed by the calling activity will be returned.
    308      *
    309      * @param enabledOnly if true then only the providers which are currently
    310      * enabled are returned.
    311      * @return list of Strings containing names of the providers
    312      */
    313     public List<String> getProviders(boolean enabledOnly) {
    314         try {
    315             return mService.getProviders(null, enabledOnly);
    316         } catch (RemoteException ex) {
    317             Log.e(TAG, "getProviders: RemoteException", ex);
    318         }
    319         return null;
    320     }
    321 
    322     /**
    323      * Returns the information associated with the location provider of the
    324      * given name, or null if no provider exists by that name.
    325      *
    326      * @param name the provider name
    327      * @return a LocationProvider, or null
    328      *
    329      * @throws IllegalArgumentException if name is null
    330      * @throws SecurityException if the caller is not permitted to access the
    331      * given provider.
    332      */
    333     public LocationProvider getProvider(String name) {
    334         if (name == null) {
    335             throw new IllegalArgumentException("name==null");
    336         }
    337         try {
    338             Bundle info = mService.getProviderInfo(name);
    339             if (info == null) {
    340                 return null;
    341             }
    342             return createProvider(name, info);
    343         } catch (RemoteException ex) {
    344             Log.e(TAG, "getProvider: RemoteException", ex);
    345         }
    346         return null;
    347     }
    348 
    349     /**
    350      * Returns a list of the names of LocationProviders that satisfy the given
    351      * criteria, or null if none do.  Only providers that are permitted to be
    352      * accessed by the calling activity will be returned.
    353      *
    354      * @param criteria the criteria that the returned providers must match
    355      * @param enabledOnly if true then only the providers which are currently
    356      * enabled are returned.
    357      * @return list of Strings containing names of the providers
    358      */
    359     public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
    360         if (criteria == null) {
    361             throw new IllegalArgumentException("criteria==null");
    362         }
    363         try {
    364             return mService.getProviders(criteria, enabledOnly);
    365         } catch (RemoteException ex) {
    366             Log.e(TAG, "getProviders: RemoteException", ex);
    367         }
    368         return null;
    369     }
    370 
    371     /**
    372      * Returns the name of the provider that best meets the given criteria. Only providers
    373      * that are permitted to be accessed by the calling activity will be
    374      * returned.  If several providers meet the criteria, the one with the best
    375      * accuracy is returned.  If no provider meets the criteria,
    376      * the criteria are loosened in the following sequence:
    377      *
    378      * <ul>
    379      * <li> power requirement
    380      * <li> accuracy
    381      * <li> bearing
    382      * <li> speed
    383      * <li> altitude
    384      * </ul>
    385      *
    386      * <p> Note that the requirement on monetary cost is not removed
    387      * in this process.
    388      *
    389      * @param criteria the criteria that need to be matched
    390      * @param enabledOnly if true then only a provider that is currently enabled is returned
    391      * @return name of the provider that best matches the requirements
    392      */
    393     public String getBestProvider(Criteria criteria, boolean enabledOnly) {
    394         if (criteria == null) {
    395             throw new IllegalArgumentException("criteria==null");
    396         }
    397         try {
    398             return mService.getBestProvider(criteria, enabledOnly);
    399         } catch (RemoteException ex) {
    400             Log.e(TAG, "getBestProvider: RemoteException", ex);
    401         }
    402         return null;
    403     }
    404 
    405     /**
    406      * Registers the current activity to be notified periodically by
    407      * the named provider.  Periodically, the supplied LocationListener will
    408      * be called with the current Location or with status updates.
    409      *
    410      * <p> It may take a while to receive the first location update. If
    411      * an immediate location is required, applications may use the
    412      * {@link #getLastKnownLocation(String)} method.
    413      *
    414      * <p> In case the provider is disabled by the user, updates will stop,
    415      * and the {@link LocationListener#onProviderDisabled(String)}
    416      * method will be called. As soon as the provider is enabled again,
    417      * the {@link LocationListener#onProviderEnabled(String)} method will
    418      * be called and location updates will start again.
    419      *
    420      * <p> The update interval can be controlled using the minTime parameter.
    421      * The elapsed time between location updates will never be less than
    422      * minTime, although it can be more depending on the Location Provider
    423      * implementation and the update interval requested by other applications.
    424      *
    425      * <p> Choosing a sensible value for minTime is important to conserve
    426      * battery life. Each location update requires power from
    427      * GPS, WIFI, Cell and other radios. Select a minTime value as high as
    428      * possible while still providing a reasonable user experience.
    429      * If your application is not in the foreground and showing
    430      * location to the user then your application should avoid using an active
    431      * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}),
    432      * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes)
    433      * or greater. If your application is in the foreground and showing
    434      * location to the user then it is appropriate to select a faster
    435      * update interval.
    436      *
    437      * <p> The minDistance parameter can also be used to control the
    438      * frequency of location updates. If it is greater than 0 then the
    439      * location provider will only send your application an update when
    440      * the location has changed by at least minDistance meters, AND
    441      * at least minTime milliseconds have passed. However it is more
    442      * difficult for location providers to save power using the minDistance
    443      * parameter, so minTime should be the primary tool to conserving battery
    444      * life.
    445      *
    446      * <p> If your application wants to passively observe location
    447      * updates triggered by other applications, but not consume
    448      * any additional power otherwise, then use the {@link #PASSIVE_PROVIDER}
    449      * This provider does not actively turn on or modify active location
    450      * providers, so you do not need to be as careful about minTime and
    451      * minDistance. However if your application performs heavy work
    452      * on a location update (such as network activity) then you should
    453      * select non-zero values for minTime and/or minDistance to rate-limit
    454      * your update frequency in the case another application enables a
    455      * location provider with extremely fast updates.
    456      *
    457      * <p> The calling thread must be a {@link android.os.Looper} thread such as
    458      * the main thread of the calling Activity.
    459      *
    460      * <p class="note"> Prior to Jellybean, the minTime parameter was
    461      * only a hint, and some location provider implementations ignored it.
    462      * From Jellybean and onwards it is mandatory for Android compatible
    463      * devices to observe both the minTime and minDistance parameters.
    464      *
    465      * @param provider the name of the provider with which to register
    466      * @param minTime minimum time interval between location updates, in milliseconds
    467      * @param minDistance minimum distance between location updates, in meters
    468      * @param listener a {#link LocationListener} whose
    469      * {@link LocationListener#onLocationChanged} method will be called for
    470      * each location update
    471      *
    472      * @throws IllegalArgumentException if provider is null or doesn't exist
    473      * on this device
    474      * @throws IllegalArgumentException if listener is null
    475      * @throws RuntimeException if the calling thread has no Looper
    476      * @throws SecurityException if no suitable permission is present for the provider.
    477      */
    478     public void requestLocationUpdates(String provider,
    479         long minTime, float minDistance, LocationListener listener) {
    480         if (provider == null) {
    481             throw new IllegalArgumentException("provider==null");
    482         }
    483         if (listener == null) {
    484             throw new IllegalArgumentException("listener==null");
    485         }
    486         _requestLocationUpdates(provider, null, minTime, minDistance, false, listener, null);
    487     }
    488 
    489     /**
    490      * Registers the current activity to be notified periodically by
    491      * the named provider.  Periodically, the supplied LocationListener will
    492      * be called with the current Location or with status updates.
    493      *
    494      * <p> It may take a while to receive the first location update. If
    495      * an immediate location is required, applications may use the
    496      * {@link #getLastKnownLocation(String)} method.
    497      *
    498      * <p> In case the provider is disabled by the user, updates will stop,
    499      * and the {@link LocationListener#onProviderDisabled(String)}
    500      * method will be called. As soon as the provider is enabled again,
    501      * the {@link LocationListener#onProviderEnabled(String)} method will
    502      * be called and location updates will start again.
    503      *
    504      * <p> The update interval can be controlled using the minTime parameter.
    505      * The elapsed time between location updates will never be less than
    506      * minTime, although it can be more depending on the Location Provider
    507      * implementation and the update interval requested by other applications.
    508      *
    509      * <p> Choosing a sensible value for minTime is important to conserve
    510      * battery life. Each location update requires power from
    511      * GPS, WIFI, Cell and other radios. Select a minTime value as high as
    512      * possible while still providing a reasonable user experience.
    513      * If your application is not in the foreground and showing
    514      * location to the user then your application should avoid using an active
    515      * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}),
    516      * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes)
    517      * or greater. If your application is in the foreground and showing
    518      * location to the user then it is appropriate to select a faster
    519      * update interval.
    520      *
    521      * <p> The minDistance parameter can also be used to control the
    522      * frequency of location updates. If it is greater than 0 then the
    523      * location provider will only send your application an update when
    524      * the location has changed by at least minDistance meters, AND
    525      * at least minTime milliseconds have passed. However it is more
    526      * difficult for location providers to save power using the minDistance
    527      * parameter, so minTime should be the primary tool to conserving battery
    528      * life.
    529      *
    530      * <p> If your application wants to passively observe location
    531      * updates triggered by other applications, but not consume
    532      * any additional power otherwise, then use the {@link #PASSIVE_PROVIDER}
    533      * This provider does not actively turn on or modify active location
    534      * providers, so you do not need to be as careful about minTime and
    535      * minDistance. However if your application performs heavy work
    536      * on a location update (such as network activity) then you should
    537      * select non-zero values for minTime and/or minDistance to rate-limit
    538      * your update frequency in the case another application enables a
    539      * location provider with extremely fast updates.
    540      *
    541      * <p> The supplied Looper is used to implement the callback mechanism.
    542      *
    543      * <p class="note"> Prior to Jellybean, the minTime parameter was
    544      * only a hint, and some location provider implementations ignored it.
    545      * From Jellybean and onwards it is mandatory for Android compatible
    546      * devices to observe both the minTime and minDistance parameters.
    547      *
    548      * @param provider the name of the provider with which to register
    549      * @param minTime minimum time interval between location updates, in milliseconds
    550      * @param minDistance minimum distance between location updates, in meters
    551      * @param listener a {#link LocationListener} whose
    552      * {@link LocationListener#onLocationChanged} method will be called for
    553      * each location update
    554      * @param looper a Looper object whose message queue will be used to
    555      * implement the callback mechanism, or null to make callbacks on the
    556      * main thread
    557      *
    558      * @throws IllegalArgumentException if provider is null or doesn't exist
    559      * @throws IllegalArgumentException if listener is null
    560      * @throws SecurityException if no suitable permission is present for the provider.
    561      */
    562     public void requestLocationUpdates(String provider,
    563         long minTime, float minDistance, LocationListener listener,
    564         Looper looper) {
    565         if (provider == null) {
    566             throw new IllegalArgumentException("provider==null");
    567         }
    568         if (listener == null) {
    569             throw new IllegalArgumentException("listener==null");
    570         }
    571         _requestLocationUpdates(provider, null, minTime, minDistance, false, listener, looper);
    572     }
    573 
    574     /**
    575      * Registers the current activity to be notified periodically based on
    576      * the supplied criteria.  Periodically, the supplied LocationListener will
    577      * be called with the current Location or with status updates.
    578      *
    579      * <p> It may take a while to receive the first location update. If
    580      * an immediate location is required, applications may use the
    581      * {@link #getLastKnownLocation(String)} method.
    582      *
    583      * <p> In case the provider is disabled by the user, updates will stop,
    584      * and the {@link LocationListener#onProviderDisabled(String)}
    585      * method will be called. As soon as the provider is enabled again,
    586      * the {@link LocationListener#onProviderEnabled(String)} method will
    587      * be called and location updates will start again.
    588      *
    589      * <p> The update interval can be controlled using the minTime parameter.
    590      * The elapsed time between location updates will never be less than
    591      * minTime, although it can be more depending on the Location Provider
    592      * implementation and the update interval requested by other applications.
    593      *
    594      * <p> Choosing a sensible value for minTime is important to conserve
    595      * battery life. Each location update requires power from
    596      * GPS, WIFI, Cell and other radios. Select a minTime value as high as
    597      * possible while still providing a reasonable user experience.
    598      * If your application is not in the foreground and showing
    599      * location to the user then your application should avoid using an active
    600      * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}),
    601      * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes)
    602      * or greater. If your application is in the foreground and showing
    603      * location to the user then it is appropriate to select a faster
    604      * update interval.
    605      *
    606      * <p> The minDistance parameter can also be used to control the
    607      * frequency of location updates. If it is greater than 0 then the
    608      * location provider will only send your application an update when
    609      * the location has changed by at least minDistance meters, AND
    610      * at least minTime milliseconds have passed. However it is more
    611      * difficult for location providers to save power using the minDistance
    612      * parameter, so minTime should be the primary tool to conserving battery
    613      * life.
    614      *
    615      * <p> The supplied Looper is used to implement the callback mechanism.
    616      *
    617      * <p class="note"> Prior to Jellybean, the minTime parameter was
    618      * only a hint, and some location provider implementations ignored it.
    619      * From Jellybean and onwards it is mandatory for Android compatible
    620      * devices to observe both the minTime and minDistance parameters.
    621      *
    622      * @param minTime minimum time interval between location updates, in milliseconds
    623      * @param minDistance minimum distance between location updates, in meters
    624      * @param criteria contains parameters for the location manager to choose the
    625      * appropriate provider and parameters to compute the location
    626      * @param listener a {#link LocationListener} whose
    627      * {@link LocationListener#onLocationChanged} method will be called for
    628      * each location update
    629      * @param looper a Looper object whose message queue will be used to
    630      * implement the callback mechanism, or null to make callbacks on the
    631      * main thread.
    632      *
    633      * @throws IllegalArgumentException if criteria is null
    634      * @throws IllegalArgumentException if listener is null
    635      * @throws SecurityException if no suitable permission is present for the provider.
    636      */
    637     public void requestLocationUpdates(long minTime, float minDistance,
    638             Criteria criteria, LocationListener listener, Looper looper) {
    639         if (criteria == null) {
    640             throw new IllegalArgumentException("criteria==null");
    641         }
    642         if (listener == null) {
    643             throw new IllegalArgumentException("listener==null");
    644         }
    645         _requestLocationUpdates(null, criteria, minTime, minDistance, false, listener, looper);
    646     }
    647 
    648     private void _requestLocationUpdates(String provider, Criteria criteria, long minTime,
    649             float minDistance, boolean singleShot, LocationListener listener, Looper looper) {
    650         if (minTime < 0L) {
    651             minTime = 0L;
    652         }
    653         if (minDistance < 0.0f) {
    654             minDistance = 0.0f;
    655         }
    656 
    657         try {
    658             synchronized (mListeners) {
    659                 ListenerTransport transport = mListeners.get(listener);
    660                 if (transport == null) {
    661                     transport = new ListenerTransport(listener, looper);
    662                 }
    663                 mListeners.put(listener, transport);
    664                 mService.requestLocationUpdates(provider, criteria, minTime, minDistance,
    665                         singleShot, transport, mContext.getPackageName());
    666             }
    667         } catch (RemoteException ex) {
    668             Log.e(TAG, "requestLocationUpdates: DeadObjectException", ex);
    669         }
    670     }
    671 
    672     /**
    673      * Registers the current activity to be notified periodically by
    674      * the named provider.  Periodically, the supplied PendingIntent will
    675      * be broadcast with the current Location or with status updates.
    676      *
    677      * <p> Location updates are sent with a key of
    678      * {@link #KEY_LOCATION_CHANGED} and a {@link android.location.Location} value.
    679      *
    680      * <p> It may take a while to receive the first location update. If
    681      * an immediate location is required, applications may use the
    682      * {@link #getLastKnownLocation(String)} method.
    683      *
    684      * <p> The update interval can be controlled using the minTime parameter.
    685      * The elapsed time between location updates will never be less than
    686      * minTime, although it can be more depending on the Location Provider
    687      * implementation and the update interval requested by other applications.
    688      *
    689      * <p> Choosing a sensible value for minTime is important to conserve
    690      * battery life. Each location update requires power from
    691      * GPS, WIFI, Cell and other radios. Select a minTime value as high as
    692      * possible while still providing a reasonable user experience.
    693      * If your application is not in the foreground and showing
    694      * location to the user then your application should avoid using an active
    695      * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}),
    696      * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes)
    697      * or greater. If your application is in the foreground and showing
    698      * location to the user then it is appropriate to select a faster
    699      * update interval.
    700      *
    701      * <p> The minDistance parameter can also be used to control the
    702      * frequency of location updates. If it is greater than 0 then the
    703      * location provider will only send your application an update when
    704      * the location has changed by at least minDistance meters, AND
    705      * at least minTime milliseconds have passed. However it is more
    706      * difficult for location providers to save power using the minDistance
    707      * parameter, so minTime should be the primary tool to conserving battery
    708      * life.
    709      *
    710      * <p> If your application wants to passively observe location
    711      * updates triggered by other applications, but not consume
    712      * any additional power otherwise, then use the {@link #PASSIVE_PROVIDER}
    713      * This provider does not actively turn on or modify active location
    714      * providers, so you do not need to be as careful about minTime and
    715      * minDistance. However if your application performs heavy work
    716      * on a location update (such as network activity) then you should
    717      * select non-zero values for minTime and/or minDistance to rate-limit
    718      * your update frequency in the case another application enables a
    719      * location provider with extremely fast updates.
    720      *
    721      * <p> If the provider is disabled by the user, updates will stop,
    722      * and an intent will be sent with an extra with key
    723      * {@link #KEY_PROVIDER_ENABLED} and a boolean value of false.
    724      * If the provider is re-enabled, an intent will be sent with an
    725      * extra with key {@link #KEY_PROVIDER_ENABLED} and a boolean value of
    726      * true and location updates will start again.
    727      *
    728      * <p> If the provider's status changes, an intent will be sent with
    729      * an extra with key {@link #KEY_STATUS_CHANGED} and an integer value
    730      * indicating the new status.  Any extras associated with the status
    731      * update will be sent as well.
    732      *
    733      * <p class="note"> Prior to Jellybean, the minTime parameter was
    734      * only a hint, and some location provider implementations ignored it.
    735      * From Jellybean and onwards it is mandatory for Android compatible
    736      * devices to observe both the minTime and minDistance parameters.
    737      *
    738      * @param provider the name of the provider with which to register
    739      * @param minTime minimum time interval between location updates, in milliseconds
    740      * @param minDistance minimum distance between location updates, in meters
    741      * @param intent a {#link PendingIntent} to be sent for each location update
    742      *
    743      * @throws IllegalArgumentException if provider is null or doesn't exist
    744      * on this device
    745      * @throws IllegalArgumentException if intent is null
    746      * @throws SecurityException if no suitable permission is present for the provider.
    747      */
    748     public void requestLocationUpdates(String provider,
    749             long minTime, float minDistance, PendingIntent intent) {
    750         if (provider == null) {
    751             throw new IllegalArgumentException("provider==null");
    752         }
    753         if (intent == null) {
    754             throw new IllegalArgumentException("intent==null");
    755         }
    756         _requestLocationUpdates(provider, null, minTime, minDistance, false, intent);
    757     }
    758 
    759     /**
    760      * Registers the current activity to be notified periodically based on
    761      * the supplied criteria.  Periodically, the supplied PendingIntent will
    762      * be broadcast with the current Location or with status updates.
    763      *
    764      * <p> Location updates are sent with a key of
    765      * {@link #KEY_LOCATION_CHANGED} and a {@link android.location.Location} value.
    766      *
    767      * <p> It may take a while to receive the first location update. If
    768      * an immediate location is required, applications may use the
    769      * {@link #getLastKnownLocation(String)} method.
    770      *
    771      * <p> The update interval can be controlled using the minTime parameter.
    772      * The elapsed time between location updates will never be less than
    773      * minTime, although it can be more depending on the Location Provider
    774      * implementation and the update interval requested by other applications.
    775      *
    776      * <p> Choosing a sensible value for minTime is important to conserve
    777      * battery life. Each location update requires power from
    778      * GPS, WIFI, Cell and other radios. Select a minTime value as high as
    779      * possible while still providing a reasonable user experience.
    780      * If your application is not in the foreground and showing
    781      * location to the user then your application should avoid using an active
    782      * provider (such as {@link #NETWORK_PROVIDER} or {@link #GPS_PROVIDER}),
    783      * but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes)
    784      * or greater. If your application is in the foreground and showing
    785      * location to the user then it is appropriate to select a faster
    786      * update interval.
    787      *
    788      * <p> The minDistance parameter can also be used to control the
    789      * frequency of location updates. If it is greater than 0 then the
    790      * location provider will only send your application an update when
    791      * the location has changed by at least minDistance meters, AND
    792      * at least minTime milliseconds have passed. However it is more
    793      * difficult for location providers to save power using the minDistance
    794      * parameter, so minTime should be the primary tool to conserving battery
    795      * life.
    796      *
    797      * <p> If the provider is disabled by the user, updates will stop,
    798      * and an intent will be sent with an extra with key
    799      * {@link #KEY_PROVIDER_ENABLED} and a boolean value of false.
    800      * If the provider is re-enabled, an intent will be sent with an
    801      * extra with key {@link #KEY_PROVIDER_ENABLED} and a boolean value of
    802      * true and location updates will start again.
    803      *
    804      * <p> If the provider's status changes, an intent will be sent with
    805      * an extra with key {@link #KEY_STATUS_CHANGED} and an integer value
    806      * indicating the new status.  Any extras associated with the status
    807      * update will be sent as well.
    808      *
    809      * <p class="note"> Prior to Jellybean, the minTime parameter was
    810      * only a hint, and some location provider implementations ignored it.
    811      * From Jellybean and onwards it is mandatory for Android compatible
    812      * devices to observe both the minTime and minDistance parameters.
    813      *
    814      * @param minTime minimum time interval between location updates, in milliseconds
    815      * @param minDistance minimum distance between location updates, in meters
    816      * @param criteria contains parameters for the location manager to choose the
    817      * appropriate provider and parameters to compute the location
    818      * @param intent a {#link PendingIntent} to be sent for each location update
    819      *
    820      * @throws IllegalArgumentException if criteria is null
    821      * @throws IllegalArgumentException if intent is null
    822      * @throws SecurityException if no suitable permission is present for the provider.
    823      */
    824     public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria,
    825             PendingIntent intent) {
    826         if (criteria == null) {
    827             throw new IllegalArgumentException("criteria==null");
    828         }
    829         if (intent == null) {
    830             throw new IllegalArgumentException("intent==null");
    831         }
    832         _requestLocationUpdates(null, criteria, minTime, minDistance, false, intent);
    833     }
    834 
    835     private void _requestLocationUpdates(String provider, Criteria criteria,
    836             long minTime, float minDistance, boolean singleShot, PendingIntent intent) {
    837         if (minTime < 0L) {
    838             minTime = 0L;
    839         }
    840         if (minDistance < 0.0f) {
    841             minDistance = 0.0f;
    842         }
    843 
    844         try {
    845             mService.requestLocationUpdatesPI(provider, criteria, minTime, minDistance, singleShot,
    846                     intent, mContext.getPackageName());
    847         } catch (RemoteException ex) {
    848             Log.e(TAG, "requestLocationUpdates: RemoteException", ex);
    849         }
    850     }
    851 
    852     /**
    853      * Requests a single location update from the named provider.
    854      *
    855      * <p> It may take a while to receive the most recent location. If
    856      * an immediate location is required, applications may use the
    857      * {@link #getLastKnownLocation(String)} method.
    858      *
    859      * <p> In case the provider is disabled by the user, the update will not be received,
    860      * and the {@link LocationListener#onProviderDisabled(String)}
    861      * method will be called. As soon as the provider is enabled again,
    862      * the {@link LocationListener#onProviderEnabled(String)} method will
    863      * be called and location updates will start again.
    864      *
    865      * <p> The supplied Looper is used to implement the callback mechanism.
    866      *
    867      * @param provider the name of the provider with which to register
    868      * @param listener a {#link LocationListener} whose
    869      * {@link LocationListener#onLocationChanged} method will be called when
    870      * the location update is available
    871      * @param looper a Looper object whose message queue will be used to
    872      * implement the callback mechanism, or null to make callbacks on the
    873      * main thread
    874      *
    875      * @throws IllegalArgumentException if provider is null or doesn't exist
    876      * @throws IllegalArgumentException if listener is null
    877      * @throws SecurityException if no suitable permission is present for the provider
    878      */
    879     public void requestSingleUpdate(String provider, LocationListener listener, Looper looper) {
    880         if (provider == null) {
    881             throw new IllegalArgumentException("provider==null");
    882         }
    883         if (listener == null) {
    884             throw new IllegalArgumentException("listener==null");
    885         }
    886         _requestLocationUpdates(provider, null, 0L, 0.0f, true, listener, looper);
    887     }
    888 
    889     /**
    890      * Requests a single location update based on the specified criteria.
    891      *
    892      * <p> It may take a while to receive the most recent location. If
    893      * an immediate location is required, applications may use the
    894      * {@link #getLastKnownLocation(String)} method.
    895      *
    896      * <p> In case the provider is disabled by the user, the update will not be received,
    897      * and the {@link LocationListener#onProviderDisabled(String)}
    898      * method will be called. As soon as the provider is enabled again,
    899      * the {@link LocationListener#onProviderEnabled(String)} method will
    900      * be called and location updates will start again.
    901      *
    902      * <p> The supplied Looper is used to implement the callback mechanism.
    903      *
    904      * @param criteria contains parameters for the location manager to choose the
    905      * appropriate provider and parameters to compute the location
    906      * @param listener a {#link LocationListener} whose
    907      * {@link LocationListener#onLocationChanged} method will be called when
    908      * the location update is available
    909      * @param looper a Looper object whose message queue will be used to
    910      * implement the callback mechanism, or null to make callbacks on the
    911      * main thread
    912      *
    913      * @throws IllegalArgumentException if criteria is null
    914      * @throws IllegalArgumentException if listener is null
    915      * @throws SecurityException if no suitable permission is present to access
    916      * the location services
    917      */
    918     public void requestSingleUpdate(Criteria criteria, LocationListener listener, Looper looper) {
    919         if (criteria == null) {
    920             throw new IllegalArgumentException("criteria==null");
    921         }
    922         if (listener == null) {
    923             throw new IllegalArgumentException("listener==null");
    924         }
    925         _requestLocationUpdates(null, criteria, 0L, 0.0f, true, listener, looper);
    926     }
    927 
    928     /**
    929      * Requests a single location update from the named provider.
    930      *
    931      * <p> It may take a while to receive the most recent location. If
    932      * an immediate location is required, applications may use the
    933      * {@link #getLastKnownLocation(String)} method.
    934      *
    935      * <p> Location updates are sent with a key of
    936      * {@link #KEY_LOCATION_CHANGED} and a {@link android.location.Location} value.
    937      *
    938      * <p> In case the provider is disabled by the user, the update will not be received,
    939      * and the {@link LocationListener#onProviderDisabled(String)}
    940      * method will be called. As soon as the provider is enabled again,
    941      * the {@link LocationListener#onProviderEnabled(String)} method will
    942      * be called and location updates will start again.
    943      *
    944      * @param provider the name of the provider with which to register
    945      * @param intent a {#link PendingIntent} to be sent for the location update
    946      *
    947      * @throws IllegalArgumentException if provider is null or doesn't exist
    948      * @throws IllegalArgumentException if intent is null
    949      * @throws SecurityException if no suitable permission is present for the provider
    950      */
    951     public void requestSingleUpdate(String provider, PendingIntent intent) {
    952         if (provider == null) {
    953             throw new IllegalArgumentException("provider==null");
    954         }
    955         if (intent == null) {
    956             throw new IllegalArgumentException("intent==null");
    957         }
    958         _requestLocationUpdates(provider, null, 0L, 0.0f, true, intent);
    959     }
    960 
    961     /**
    962      * Requests a single location update based on the specified criteria.
    963      *
    964      * <p> It may take a while to receive the most recent location. If
    965      * an immediate location is required, applications may use the
    966      * {@link #getLastKnownLocation(String)} method.
    967      *
    968      * <p> Location updates are sent with a key of
    969      * {@link #KEY_LOCATION_CHANGED} and a {@link android.location.Location} value.
    970      *
    971      * <p> If the provider is disabled by the user, an update will not be
    972      * received, and an intent will be sent with an extra with key
    973      * {@link #KEY_PROVIDER_ENABLED} and a boolean value of false.
    974      * If the provider is re-enabled, an intent will be sent with an
    975      * extra with key {@link #KEY_PROVIDER_ENABLED} and a boolean value of
    976      * true and the location update will occur.
    977      *
    978      * @param criteria contains parameters for the location manager to choose the
    979      * appropriate provider and parameters to compute the location
    980      * @param intent a {#link PendingIntent} to be sent for the location update
    981      *
    982      * @throws IllegalArgumentException if provider is null or doesn't exist
    983      * @throws IllegalArgumentException if intent is null
    984      * @throws SecurityException if no suitable permission is present for the provider
    985      */
    986     public void requestSingleUpdate(Criteria criteria, PendingIntent intent) {
    987         if (criteria == null) {
    988             throw new IllegalArgumentException("criteria==null");
    989         }
    990         if (intent == null) {
    991             throw new IllegalArgumentException("intent==null");
    992         }
    993         _requestLocationUpdates(null, criteria, 0L, 0.0f, true, intent);
    994     }
    995 
    996     /**
    997      * Removes any current registration for location updates of the current activity
    998      * with the given LocationListener.  Following this call, updates will no longer
    999      * occur for this listener.
   1000      *
   1001      * @param listener {#link LocationListener} object that no longer needs location updates
   1002      * @throws IllegalArgumentException if listener is null
   1003      */
   1004     public void removeUpdates(LocationListener listener) {
   1005         if (listener == null) {
   1006             throw new IllegalArgumentException("listener==null");
   1007         }
   1008         if (false) {
   1009             Log.d(TAG, "removeUpdates: listener = " + listener);
   1010         }
   1011         try {
   1012             ListenerTransport transport = mListeners.remove(listener);
   1013             if (transport != null) {
   1014                 mService.removeUpdates(transport, mContext.getPackageName());
   1015             }
   1016         } catch (RemoteException ex) {
   1017             Log.e(TAG, "removeUpdates: DeadObjectException", ex);
   1018         }
   1019     }
   1020 
   1021     /**
   1022      * Removes any current registration for location updates of the current activity
   1023      * with the given PendingIntent.  Following this call, updates will no longer
   1024      * occur for this intent.
   1025      *
   1026      * @param intent {#link PendingIntent} object that no longer needs location updates
   1027      * @throws IllegalArgumentException if intent is null
   1028      */
   1029     public void removeUpdates(PendingIntent intent) {
   1030         if (intent == null) {
   1031             throw new IllegalArgumentException("intent==null");
   1032         }
   1033         if (false) {
   1034             Log.d(TAG, "removeUpdates: intent = " + intent);
   1035         }
   1036         try {
   1037             mService.removeUpdatesPI(intent, mContext.getPackageName());
   1038         } catch (RemoteException ex) {
   1039             Log.e(TAG, "removeUpdates: RemoteException", ex);
   1040         }
   1041     }
   1042 
   1043     /**
   1044      * Sets a proximity alert for the location given by the position
   1045      * (latitude, longitude) and the given radius.  When the device
   1046      * detects that it has entered or exited the area surrounding the
   1047      * location, the given PendingIntent will be used to create an Intent
   1048      * to be fired.
   1049      *
   1050      * <p> The fired Intent will have a boolean extra added with key
   1051      * {@link #KEY_PROXIMITY_ENTERING}. If the value is true, the device is
   1052      * entering the proximity region; if false, it is exiting.
   1053      *
   1054      * <p> Due to the approximate nature of position estimation, if the
   1055      * device passes through the given area briefly, it is possible
   1056      * that no Intent will be fired.  Similarly, an Intent could be
   1057      * fired if the device passes very close to the given area but
   1058      * does not actually enter it.
   1059      *
   1060      * <p> After the number of milliseconds given by the expiration
   1061      * parameter, the location manager will delete this proximity
   1062      * alert and no longer monitor it.  A value of -1 indicates that
   1063      * there should be no expiration time.
   1064      *
   1065      * <p> In case the screen goes to sleep, checks for proximity alerts
   1066      * happen only once every 4 minutes. This conserves battery life by
   1067      * ensuring that the device isn't perpetually awake.
   1068      *
   1069      * <p> Internally, this method uses both {@link #NETWORK_PROVIDER}
   1070      * and {@link #GPS_PROVIDER}.
   1071      *
   1072      * @param latitude the latitude of the central point of the
   1073      * alert region
   1074      * @param longitude the longitude of the central point of the
   1075      * alert region
   1076      * @param radius the radius of the central point of the
   1077      * alert region, in meters
   1078      * @param expiration time for this proximity alert, in milliseconds,
   1079      * or -1 to indicate no expiration
   1080      * @param intent a PendingIntent that will be used to generate an Intent to
   1081      * fire when entry to or exit from the alert region is detected
   1082      *
   1083      * @throws SecurityException if no permission exists for the required
   1084      * providers.
   1085      */
   1086     public void addProximityAlert(double latitude, double longitude,
   1087         float radius, long expiration, PendingIntent intent) {
   1088         if (false) {
   1089             Log.d(TAG, "addProximityAlert: latitude = " + latitude +
   1090                 ", longitude = " + longitude + ", radius = " + radius +
   1091                 ", expiration = " + expiration +
   1092                 ", intent = " + intent);
   1093         }
   1094         try {
   1095             mService.addProximityAlert(latitude, longitude, radius,
   1096                                        expiration, intent, mContext.getPackageName());
   1097         } catch (RemoteException ex) {
   1098             Log.e(TAG, "addProximityAlert: RemoteException", ex);
   1099         }
   1100     }
   1101 
   1102     /**
   1103      * Removes the proximity alert with the given PendingIntent.
   1104      *
   1105      * @param intent the PendingIntent that no longer needs to be notified of
   1106      * proximity alerts
   1107      */
   1108     public void removeProximityAlert(PendingIntent intent) {
   1109         if (false) {
   1110             Log.d(TAG, "removeProximityAlert: intent = " + intent);
   1111         }
   1112         try {
   1113             mService.removeProximityAlert(intent);
   1114         } catch (RemoteException ex) {
   1115             Log.e(TAG, "removeProximityAlert: RemoteException", ex);
   1116         }
   1117     }
   1118 
   1119     /**
   1120      * Returns the current enabled/disabled status of the given provider. If the
   1121      * user has enabled this provider in the Settings menu, true is returned
   1122      * otherwise false is returned
   1123      *
   1124      * @param provider the name of the provider
   1125      * @return true if the provider is enabled
   1126      *
   1127      * @throws SecurityException if no suitable permission is present for the provider.
   1128      * @throws IllegalArgumentException if provider is null
   1129      */
   1130     public boolean isProviderEnabled(String provider) {
   1131         if (provider == null) {
   1132             throw new IllegalArgumentException("provider==null");
   1133         }
   1134         try {
   1135             return mService.isProviderEnabled(provider);
   1136         } catch (RemoteException ex) {
   1137             Log.e(TAG, "isProviderEnabled: RemoteException", ex);
   1138             return false;
   1139         }
   1140     }
   1141 
   1142     /**
   1143      * Returns a Location indicating the data from the last known
   1144      * location fix obtained from the given provider.  This can be done
   1145      * without starting the provider.  Note that this location could
   1146      * be out-of-date, for example if the device was turned off and
   1147      * moved to another location.
   1148      *
   1149      * <p> If the provider is currently disabled, null is returned.
   1150      *
   1151      * @param provider the name of the provider
   1152      * @return the last known location for the provider, or null
   1153      *
   1154      * @throws SecurityException if no suitable permission is present for the provider.
   1155      * @throws IllegalArgumentException if provider is null or doesn't exist
   1156      */
   1157     public Location getLastKnownLocation(String provider) {
   1158         if (provider == null) {
   1159             throw new IllegalArgumentException("provider==null");
   1160         }
   1161         try {
   1162             return mService.getLastKnownLocation(provider, mContext.getPackageName());
   1163         } catch (RemoteException ex) {
   1164             Log.e(TAG, "getLastKnowLocation: RemoteException", ex);
   1165             return null;
   1166         }
   1167     }
   1168 
   1169     // Mock provider support
   1170 
   1171     /**
   1172      * Creates a mock location provider and adds it to the set of active providers.
   1173      *
   1174      * @param name the provider name
   1175      * @param requiresNetwork
   1176      * @param requiresSatellite
   1177      * @param requiresCell
   1178      * @param hasMonetaryCost
   1179      * @param supportsAltitude
   1180      * @param supportsSpeed
   1181      * @param supportsBearing
   1182      * @param powerRequirement
   1183      * @param accuracy
   1184      *
   1185      * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present
   1186      * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION
   1187      * Settings.Secure.ALLOW_MOCK_LOCATION} system setting is not enabled
   1188      * @throws IllegalArgumentException if a provider with the given name already exists
   1189      */
   1190     public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite,
   1191         boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
   1192         boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
   1193         try {
   1194             mService.addTestProvider(name, requiresNetwork, requiresSatellite, requiresCell,
   1195                 hasMonetaryCost, supportsAltitude, supportsSpeed, supportsBearing, powerRequirement,
   1196                 accuracy);
   1197         } catch (RemoteException ex) {
   1198             Log.e(TAG, "addTestProvider: RemoteException", ex);
   1199         }
   1200     }
   1201 
   1202     /**
   1203      * Removes the mock location provider with the given name.
   1204      *
   1205      * @param provider the provider name
   1206      *
   1207      * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present
   1208      * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION
   1209      * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
   1210      * @throws IllegalArgumentException if no provider with the given name exists
   1211      */
   1212     public void removeTestProvider(String provider) {
   1213         try {
   1214             mService.removeTestProvider(provider);
   1215         } catch (RemoteException ex) {
   1216             Log.e(TAG, "removeTestProvider: RemoteException", ex);
   1217         }
   1218     }
   1219 
   1220     /**
   1221      * Sets a mock location for the given provider.  This location will be used in place
   1222      * of any actual location from the provider.
   1223      *
   1224      * @param provider the provider name
   1225      * @param loc the mock location
   1226      *
   1227      * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present
   1228      * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION
   1229      * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
   1230      * @throws IllegalArgumentException if no provider with the given name exists
   1231      */
   1232     public void setTestProviderLocation(String provider, Location loc) {
   1233         try {
   1234             mService.setTestProviderLocation(provider, loc);
   1235         } catch (RemoteException ex) {
   1236             Log.e(TAG, "setTestProviderLocation: RemoteException", ex);
   1237         }
   1238     }
   1239 
   1240     /**
   1241      * Removes any mock location associated with the given provider.
   1242      *
   1243      * @param provider the provider name
   1244      *
   1245      * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present
   1246      * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION
   1247      * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
   1248      * @throws IllegalArgumentException if no provider with the given name exists
   1249      */
   1250     public void clearTestProviderLocation(String provider) {
   1251         try {
   1252             mService.clearTestProviderLocation(provider);
   1253         } catch (RemoteException ex) {
   1254             Log.e(TAG, "clearTestProviderLocation: RemoteException", ex);
   1255         }
   1256     }
   1257 
   1258     /**
   1259      * Sets a mock enabled value for the given provider.  This value will be used in place
   1260      * of any actual value from the provider.
   1261      *
   1262      * @param provider the provider name
   1263      * @param enabled the mock enabled value
   1264      *
   1265      * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present
   1266      * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION
   1267      * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
   1268      * @throws IllegalArgumentException if no provider with the given name exists
   1269      */
   1270     public void setTestProviderEnabled(String provider, boolean enabled) {
   1271         try {
   1272             mService.setTestProviderEnabled(provider, enabled);
   1273         } catch (RemoteException ex) {
   1274             Log.e(TAG, "setTestProviderEnabled: RemoteException", ex);
   1275         }
   1276     }
   1277 
   1278     /**
   1279      * Removes any mock enabled value associated with the given provider.
   1280      *
   1281      * @param provider the provider name
   1282      *
   1283      * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present
   1284      * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION
   1285      * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
   1286      * @throws IllegalArgumentException if no provider with the given name exists
   1287      */
   1288     public void clearTestProviderEnabled(String provider) {
   1289         try {
   1290             mService.clearTestProviderEnabled(provider);
   1291         } catch (RemoteException ex) {
   1292             Log.e(TAG, "clearTestProviderEnabled: RemoteException", ex);
   1293         }
   1294 
   1295     }
   1296 
   1297     /**
   1298      * Sets mock status values for the given provider.  These values will be used in place
   1299      * of any actual values from the provider.
   1300      *
   1301      * @param provider the provider name
   1302      * @param status the mock status
   1303      * @param extras a Bundle containing mock extras
   1304      * @param updateTime the mock update time
   1305      *
   1306      * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present
   1307      * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION
   1308      * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
   1309      * @throws IllegalArgumentException if no provider with the given name exists
   1310      */
   1311     public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) {
   1312         try {
   1313             mService.setTestProviderStatus(provider, status, extras, updateTime);
   1314         } catch (RemoteException ex) {
   1315             Log.e(TAG, "setTestProviderStatus: RemoteException", ex);
   1316         }
   1317     }
   1318 
   1319     /**
   1320      * Removes any mock status values associated with the given provider.
   1321      *
   1322      * @param provider the provider name
   1323      *
   1324      * @throws SecurityException if the ACCESS_MOCK_LOCATION permission is not present
   1325      * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION
   1326      * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled
   1327      * @throws IllegalArgumentException if no provider with the given name exists
   1328      */
   1329     public void clearTestProviderStatus(String provider) {
   1330         try {
   1331             mService.clearTestProviderStatus(provider);
   1332         } catch (RemoteException ex) {
   1333             Log.e(TAG, "clearTestProviderStatus: RemoteException", ex);
   1334         }
   1335     }
   1336 
   1337     // GPS-specific support
   1338 
   1339     // This class is used to send GPS status events to the client's main thread.
   1340     private class GpsStatusListenerTransport extends IGpsStatusListener.Stub {
   1341 
   1342         private final GpsStatus.Listener mListener;
   1343         private final GpsStatus.NmeaListener mNmeaListener;
   1344 
   1345         // This must not equal any of the GpsStatus event IDs
   1346         private static final int NMEA_RECEIVED = 1000;
   1347 
   1348         private class Nmea {
   1349             long mTimestamp;
   1350             String mNmea;
   1351 
   1352             Nmea(long timestamp, String nmea) {
   1353                 mTimestamp = timestamp;
   1354                 mNmea = nmea;
   1355             }
   1356         }
   1357         private ArrayList<Nmea> mNmeaBuffer;
   1358 
   1359         GpsStatusListenerTransport(GpsStatus.Listener listener) {
   1360             mListener = listener;
   1361             mNmeaListener = null;
   1362         }
   1363 
   1364         GpsStatusListenerTransport(GpsStatus.NmeaListener listener) {
   1365             mNmeaListener = listener;
   1366             mListener = null;
   1367             mNmeaBuffer = new ArrayList<Nmea>();
   1368         }
   1369 
   1370         public void onGpsStarted() {
   1371             if (mListener != null) {
   1372                 Message msg = Message.obtain();
   1373                 msg.what = GpsStatus.GPS_EVENT_STARTED;
   1374                 mGpsHandler.sendMessage(msg);
   1375             }
   1376         }
   1377 
   1378         public void onGpsStopped() {
   1379             if (mListener != null) {
   1380                 Message msg = Message.obtain();
   1381                 msg.what = GpsStatus.GPS_EVENT_STOPPED;
   1382                 mGpsHandler.sendMessage(msg);
   1383             }
   1384         }
   1385 
   1386         public void onFirstFix(int ttff) {
   1387             if (mListener != null) {
   1388                 mGpsStatus.setTimeToFirstFix(ttff);
   1389                 Message msg = Message.obtain();
   1390                 msg.what = GpsStatus.GPS_EVENT_FIRST_FIX;
   1391                 mGpsHandler.sendMessage(msg);
   1392             }
   1393         }
   1394 
   1395         public void onSvStatusChanged(int svCount, int[] prns, float[] snrs,
   1396                 float[] elevations, float[] azimuths, int ephemerisMask,
   1397                 int almanacMask, int usedInFixMask) {
   1398             if (mListener != null) {
   1399                 mGpsStatus.setStatus(svCount, prns, snrs, elevations, azimuths,
   1400                         ephemerisMask, almanacMask, usedInFixMask);
   1401 
   1402                 Message msg = Message.obtain();
   1403                 msg.what = GpsStatus.GPS_EVENT_SATELLITE_STATUS;
   1404                 // remove any SV status messages already in the queue
   1405                 mGpsHandler.removeMessages(GpsStatus.GPS_EVENT_SATELLITE_STATUS);
   1406                 mGpsHandler.sendMessage(msg);
   1407             }
   1408         }
   1409 
   1410         public void onNmeaReceived(long timestamp, String nmea) {
   1411             if (mNmeaListener != null) {
   1412                 synchronized (mNmeaBuffer) {
   1413                     mNmeaBuffer.add(new Nmea(timestamp, nmea));
   1414                 }
   1415                 Message msg = Message.obtain();
   1416                 msg.what = NMEA_RECEIVED;
   1417                 // remove any NMEA_RECEIVED messages already in the queue
   1418                 mGpsHandler.removeMessages(NMEA_RECEIVED);
   1419                 mGpsHandler.sendMessage(msg);
   1420             }
   1421         }
   1422 
   1423         private final Handler mGpsHandler = new Handler() {
   1424             @Override
   1425             public void handleMessage(Message msg) {
   1426                 if (msg.what == NMEA_RECEIVED) {
   1427                     synchronized (mNmeaBuffer) {
   1428                         int length = mNmeaBuffer.size();
   1429                         for (int i = 0; i < length; i++) {
   1430                             Nmea nmea = mNmeaBuffer.get(i);
   1431                             mNmeaListener.onNmeaReceived(nmea.mTimestamp, nmea.mNmea);
   1432                         }
   1433                         mNmeaBuffer.clear();
   1434                     }
   1435                 } else {
   1436                     // synchronize on mGpsStatus to ensure the data is copied atomically.
   1437                     synchronized(mGpsStatus) {
   1438                         mListener.onGpsStatusChanged(msg.what);
   1439                     }
   1440                 }
   1441             }
   1442         };
   1443     }
   1444 
   1445     /**
   1446      * Adds a GPS status listener.
   1447      *
   1448      * @param listener GPS status listener object to register
   1449      *
   1450      * @return true if the listener was successfully added
   1451      *
   1452      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
   1453      */
   1454     public boolean addGpsStatusListener(GpsStatus.Listener listener) {
   1455         boolean result;
   1456 
   1457         if (mGpsStatusListeners.get(listener) != null) {
   1458             // listener is already registered
   1459             return true;
   1460         }
   1461         try {
   1462             GpsStatusListenerTransport transport = new GpsStatusListenerTransport(listener);
   1463             result = mService.addGpsStatusListener(transport);
   1464             if (result) {
   1465                 mGpsStatusListeners.put(listener, transport);
   1466             }
   1467         } catch (RemoteException e) {
   1468             Log.e(TAG, "RemoteException in registerGpsStatusListener: ", e);
   1469             result = false;
   1470         }
   1471 
   1472         return result;
   1473     }
   1474 
   1475     /**
   1476      * Removes a GPS status listener.
   1477      *
   1478      * @param listener GPS status listener object to remove
   1479      */
   1480     public void removeGpsStatusListener(GpsStatus.Listener listener) {
   1481         try {
   1482             GpsStatusListenerTransport transport = mGpsStatusListeners.remove(listener);
   1483             if (transport != null) {
   1484                 mService.removeGpsStatusListener(transport);
   1485             }
   1486         } catch (RemoteException e) {
   1487             Log.e(TAG, "RemoteException in unregisterGpsStatusListener: ", e);
   1488         }
   1489     }
   1490 
   1491     /**
   1492      * Adds an NMEA listener.
   1493      *
   1494      * @param listener a {#link GpsStatus.NmeaListener} object to register
   1495      *
   1496      * @return true if the listener was successfully added
   1497      *
   1498      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
   1499      */
   1500     public boolean addNmeaListener(GpsStatus.NmeaListener listener) {
   1501         boolean result;
   1502 
   1503         if (mNmeaListeners.get(listener) != null) {
   1504             // listener is already registered
   1505             return true;
   1506         }
   1507         try {
   1508             GpsStatusListenerTransport transport = new GpsStatusListenerTransport(listener);
   1509             result = mService.addGpsStatusListener(transport);
   1510             if (result) {
   1511                 mNmeaListeners.put(listener, transport);
   1512             }
   1513         } catch (RemoteException e) {
   1514             Log.e(TAG, "RemoteException in registerGpsStatusListener: ", e);
   1515             result = false;
   1516         }
   1517 
   1518         return result;
   1519     }
   1520 
   1521     /**
   1522      * Removes an NMEA listener.
   1523      *
   1524      * @param listener a {#link GpsStatus.NmeaListener} object to remove
   1525      */
   1526     public void removeNmeaListener(GpsStatus.NmeaListener listener) {
   1527         try {
   1528             GpsStatusListenerTransport transport = mNmeaListeners.remove(listener);
   1529             if (transport != null) {
   1530                 mService.removeGpsStatusListener(transport);
   1531             }
   1532         } catch (RemoteException e) {
   1533             Log.e(TAG, "RemoteException in unregisterGpsStatusListener: ", e);
   1534         }
   1535     }
   1536 
   1537      /**
   1538      * Retrieves information about the current status of the GPS engine.
   1539      * This should only be called from the {@link GpsStatus.Listener#onGpsStatusChanged}
   1540      * callback to ensure that the data is copied atomically.
   1541      *
   1542      * The caller may either pass in a {@link GpsStatus} object to set with the latest
   1543      * status information, or pass null to create a new {@link GpsStatus} object.
   1544      *
   1545      * @param status object containing GPS status details, or null.
   1546      * @return status object containing updated GPS status.
   1547      */
   1548     public GpsStatus getGpsStatus(GpsStatus status) {
   1549         if (status == null) {
   1550             status = new GpsStatus();
   1551        }
   1552        status.setStatus(mGpsStatus);
   1553        return status;
   1554     }
   1555 
   1556     /**
   1557      * Sends additional commands to a location provider.
   1558      * Can be used to support provider specific extensions to the Location Manager API
   1559      *
   1560      * @param provider name of the location provider.
   1561      * @param command name of the command to send to the provider.
   1562      * @param extras optional arguments for the command (or null).
   1563      * The provider may optionally fill the extras Bundle with results from the command.
   1564      *
   1565      * @return true if the command succeeds.
   1566      */
   1567     public boolean sendExtraCommand(String provider, String command, Bundle extras) {
   1568         try {
   1569             return mService.sendExtraCommand(provider, command, extras);
   1570         } catch (RemoteException e) {
   1571             Log.e(TAG, "RemoteException in sendExtraCommand: ", e);
   1572             return false;
   1573         }
   1574     }
   1575 
   1576     /**
   1577      * Used by NetInitiatedActivity to report user response
   1578      * for network initiated GPS fix requests.
   1579      *
   1580      * {@hide}
   1581      */
   1582     public boolean sendNiResponse(int notifId, int userResponse) {
   1583     	try {
   1584             return mService.sendNiResponse(notifId, userResponse);
   1585         } catch (RemoteException e) {
   1586             Log.e(TAG, "RemoteException in sendNiResponse: ", e);
   1587             return false;
   1588         }
   1589     }
   1590 
   1591 }
   1592