• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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.webkit;
18 
19 import android.app.ActivityThread;
20 import android.content.Context;
21 import android.location.Location;
22 import android.location.LocationListener;
23 import android.location.LocationManager;
24 import android.location.LocationProvider;
25 import android.os.Bundle;
26 import android.util.Log;
27 import android.webkit.WebViewCore;
28 
29 
30 /**
31  * Implements the Java side of GeolocationServiceAndroid.
32  */
33 final class GeolocationService implements LocationListener {
34 
35     // Log tag
36     private static final String TAG = "geolocationService";
37 
38     private long mNativeObject;
39     private LocationManager mLocationManager;
40     private boolean mIsGpsEnabled;
41     private boolean mIsRunning;
42     private boolean mIsNetworkProviderAvailable;
43     private boolean mIsGpsProviderAvailable;
44 
45     /**
46      * Constructor
47      * @param context The context from which we obtain the system service.
48      * @param nativeObject The native object to which this object will report position updates and
49      *     errors.
50      */
GeolocationService(Context context, long nativeObject)51     public GeolocationService(Context context, long nativeObject) {
52         mNativeObject = nativeObject;
53         // Register newLocationAvailable with platform service.
54         mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
55         if (mLocationManager == null) {
56             Log.e(TAG, "Could not get location manager.");
57         }
58      }
59 
60     /**
61      * Start listening for location updates.
62      */
start()63     public boolean start() {
64         registerForLocationUpdates();
65         mIsRunning = true;
66         return mIsNetworkProviderAvailable || mIsGpsProviderAvailable;
67     }
68 
69     /**
70      * Stop listening for location updates.
71      */
stop()72     public void stop() {
73         unregisterFromLocationUpdates();
74         mIsRunning = false;
75     }
76 
77     /**
78      * Sets whether to use the GPS.
79      * @param enable Whether to use the GPS.
80      */
setEnableGps(boolean enable)81     public void setEnableGps(boolean enable) {
82         if (mIsGpsEnabled != enable) {
83             mIsGpsEnabled = enable;
84             if (mIsRunning) {
85                 // There's no way to unregister from a single provider, so we can
86                 // only unregister from all, then reregister with all but the GPS.
87                 unregisterFromLocationUpdates();
88                 registerForLocationUpdates();
89                 // Check that the providers are still available after we re-register.
90                 maybeReportError("The last location provider is no longer available");
91             }
92         }
93     }
94 
95     /**
96      * LocationListener implementation.
97      * Called when the location has changed.
98      * @param location The new location, as a Location object.
99      */
onLocationChanged(Location location)100     public void onLocationChanged(Location location) {
101         // Callbacks from the system location sevice are queued to this thread, so it's possible
102         // that we receive callbacks after unregistering. At this point, the native object will no
103         // longer exist.
104         if (mIsRunning) {
105             nativeNewLocationAvailable(mNativeObject, location);
106         }
107     }
108 
109     /**
110      * LocationListener implementation.
111      * Called when the provider status changes.
112      * @param provider The name of the provider.
113      * @param status The new status of the provider.
114      * @param extras an optional Bundle with provider specific data.
115      */
onStatusChanged(String providerName, int status, Bundle extras)116     public void onStatusChanged(String providerName, int status, Bundle extras) {
117         boolean isAvailable = (status == LocationProvider.AVAILABLE);
118         if (LocationManager.NETWORK_PROVIDER.equals(providerName)) {
119             mIsNetworkProviderAvailable = isAvailable;
120         } else if (LocationManager.GPS_PROVIDER.equals(providerName)) {
121             mIsGpsProviderAvailable = isAvailable;
122         }
123         maybeReportError("The last location provider is no longer available");
124     }
125 
126     /**
127      * LocationListener implementation.
128      * Called when the provider is enabled.
129      * @param provider The name of the location provider that is now enabled.
130      */
onProviderEnabled(String providerName)131     public void onProviderEnabled(String providerName) {
132         // No need to notify the native side. It's enough to start sending
133         // valid position fixes again.
134         if (LocationManager.NETWORK_PROVIDER.equals(providerName)) {
135             mIsNetworkProviderAvailable = true;
136         } else if (LocationManager.GPS_PROVIDER.equals(providerName)) {
137             mIsGpsProviderAvailable = true;
138         }
139     }
140 
141     /**
142      * LocationListener implementation.
143      * Called when the provider is disabled.
144      * @param provider The name of the location provider that is now disabled.
145      */
onProviderDisabled(String providerName)146     public void onProviderDisabled(String providerName) {
147         if (LocationManager.NETWORK_PROVIDER.equals(providerName)) {
148             mIsNetworkProviderAvailable = false;
149         } else if (LocationManager.GPS_PROVIDER.equals(providerName)) {
150             mIsGpsProviderAvailable = false;
151         }
152         maybeReportError("The last location provider was disabled");
153     }
154 
155     /**
156      * Registers this object with the location service.
157      */
registerForLocationUpdates()158     private void registerForLocationUpdates() {
159         try {
160             // Registration may fail if providers are not present on the device.
161             try {
162                 mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
163                 mIsNetworkProviderAvailable = true;
164             } catch(IllegalArgumentException e) { }
165             if (mIsGpsEnabled) {
166                 try {
167                     mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
168                     mIsGpsProviderAvailable = true;
169                 } catch(IllegalArgumentException e) { }
170             }
171         } catch(SecurityException e) {
172             Log.e(TAG, "Caught security exception registering for location updates from system. " +
173                 "This should only happen in DumpRenderTree.");
174         }
175     }
176 
177     /**
178      * Unregisters this object from the location service.
179      */
unregisterFromLocationUpdates()180     private void unregisterFromLocationUpdates() {
181         mLocationManager.removeUpdates(this);
182         mIsNetworkProviderAvailable = false;
183         mIsGpsProviderAvailable = false;
184     }
185 
186     /**
187      * Reports an error if neither the network nor the GPS provider is available.
188      */
maybeReportError(String message)189     private void maybeReportError(String message) {
190         // Callbacks from the system location sevice are queued to this thread, so it's possible
191         // that we receive callbacks after unregistering. At this point, the native object will no
192         // longer exist.
193         if (mIsRunning && !mIsNetworkProviderAvailable && !mIsGpsProviderAvailable) {
194             nativeNewErrorAvailable(mNativeObject, message);
195         }
196     }
197 
198     // Native functions
nativeNewLocationAvailable(long nativeObject, Location location)199     private static native void nativeNewLocationAvailable(long nativeObject, Location location);
nativeNewErrorAvailable(long nativeObject, String message)200     private static native void nativeNewErrorAvailable(long nativeObject, String message);
201 }
202