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