OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.content.browser; | 5 package org.chromium.content.browser; |
6 | 6 |
7 import android.content.Context; | 7 import android.content.Context; |
8 import android.location.Criteria; | |
9 import android.location.Location; | 8 import android.location.Location; |
10 import android.location.LocationListener; | 9 import android.os.Handler; |
11 import android.location.LocationManager; | 10 import android.os.HandlerThread; |
12 import android.os.Bundle; | 11 import android.os.Message; |
13 import android.util.Log; | |
14 | 12 |
15 import org.chromium.base.ActivityStatus; | |
16 import org.chromium.base.CalledByNative; | 13 import org.chromium.base.CalledByNative; |
17 import org.chromium.base.ThreadUtils; | 14 import org.chromium.base.ThreadUtils; |
18 | 15 |
19 import java.util.List; | 16 import com.google.common.annotations.VisibleForTesting; |
17 | |
20 import java.util.concurrent.FutureTask; | 18 import java.util.concurrent.FutureTask; |
21 | 19 |
22 /** | 20 /** |
23 * Implements the Java side of LocationProviderAndroid. | 21 * Implements the Java side of LocationProviderAndroid. |
24 * Delegates all real functionality to the inner class. | 22 * Delegates all real functionality to the implementation |
23 * returned from LocationProviderFactory. | |
25 * See detailed documentation on | 24 * See detailed documentation on |
26 * content/browser/geolocation/android_location_api_adapter.h. | 25 * content/browser/geolocation/android_location_api_adapter.h. |
27 * Based on android.webkit.GeolocationService.java | 26 * Based on android.webkit.GeolocationService.java |
28 */ | 27 */ |
29 class LocationProvider { | 28 @VisibleForTesting |
30 | 29 public class LocationProvider { |
bulach
2013/12/11 15:48:39
I think this would now be better as LocationProvid
benm (inactive)
2013/12/11 20:08:51
SGTM, done
| |
31 // Log tag | |
32 private static final String TAG = "LocationProvider"; | |
33 | |
34 /** | |
35 * This is the core of android location provider. It is a separate class for clarity | |
36 * so that it can manage all processing completely in the UI thread. The con tainer class | |
37 * ensures that the start/stop calls into this class are done in the UI thre ad. | |
38 */ | |
39 private static class LocationProviderImpl | |
40 implements LocationListener, ActivityStatus.StateListener { | |
41 | |
42 private Context mContext; | |
43 private LocationManager mLocationManager; | |
44 private boolean mIsRunning; | |
45 private boolean mShouldRunAfterActivityResume; | |
46 private boolean mIsGpsEnabled; | |
47 | |
48 LocationProviderImpl(Context context) { | |
49 mContext = context; | |
50 } | |
51 | |
52 @Override | |
53 public void onActivityStateChange(int state) { | |
54 if (state == ActivityStatus.PAUSED) { | |
55 mShouldRunAfterActivityResume |= mIsRunning; | |
56 unregisterFromLocationUpdates(); | |
57 } else if (state == ActivityStatus.RESUMED) { | |
58 assert !mIsRunning; | |
59 if (mShouldRunAfterActivityResume) { | |
60 registerForLocationUpdates(); | |
61 } | |
62 } | |
63 } | |
64 | |
65 /** | |
66 * Start listening for location updates. | |
67 * @param gpsEnabled Whether or not we're interested in high accuracy GP S. | |
68 */ | |
69 private void start(boolean gpsEnabled) { | |
70 if (!mIsRunning && !mShouldRunAfterActivityResume) { | |
71 // Currently idle so start listening to activity status changes. | |
72 ActivityStatus.registerStateListener(this); | |
73 } | |
74 mIsGpsEnabled = gpsEnabled; | |
75 | |
76 if (ActivityStatus.getState() != ActivityStatus.RESUMED) { | |
77 mShouldRunAfterActivityResume = true; | |
78 } else { | |
79 unregisterFromLocationUpdates(); | |
80 registerForLocationUpdates(); | |
81 } | |
82 } | |
83 | |
84 /** | |
85 * Stop listening for location updates. | |
86 */ | |
87 private void stop() { | |
88 unregisterFromLocationUpdates(); | |
89 ActivityStatus.unregisterStateListener(this); | |
90 mShouldRunAfterActivityResume = false; | |
91 } | |
92 | |
93 /** | |
94 * Returns true if we are currently listening for location updates, fals e if not. | |
95 */ | |
96 private boolean isRunning() { | |
97 return mIsRunning; | |
98 } | |
99 | |
100 @Override | |
101 public void onLocationChanged(Location location) { | |
102 // Callbacks from the system location sevice are queued to this thre ad, so it's | |
103 // possible that we receive callbacks after unregistering. At this p oint, the | |
104 // native object will no longer exist. | |
105 if (mIsRunning) { | |
106 updateNewLocation(location); | |
107 } | |
108 } | |
109 | |
110 private void updateNewLocation(Location location) { | |
111 nativeNewLocationAvailable(location.getLatitude(), location.getLongi tude(), | |
112 location.getTime() / 1000.0, | |
113 location.hasAltitude(), location.getAltitude(), | |
114 location.hasAccuracy(), location.getAccuracy(), | |
115 location.hasBearing(), location.getBearing(), | |
116 location.hasSpeed(), location.getSpeed()); | |
117 } | |
118 | |
119 @Override | |
120 public void onStatusChanged(String provider, int status, Bundle extras) { | |
121 } | |
122 | |
123 @Override | |
124 public void onProviderEnabled(String provider) { | |
125 } | |
126 | |
127 @Override | |
128 public void onProviderDisabled(String provider) { | |
129 } | |
130 | |
131 private void ensureLocationManagerCreated() { | |
132 if (mLocationManager != null) return; | |
133 mLocationManager = (LocationManager) mContext.getSystemService( | |
134 Context.LOCATION_SERVICE); | |
135 if (mLocationManager == null) { | |
136 Log.e(TAG, "Could not get location manager."); | |
137 } | |
138 } | |
139 | |
140 /** | |
141 * Registers this object with the location service. | |
142 */ | |
143 private void registerForLocationUpdates() { | |
144 ensureLocationManagerCreated(); | |
145 if (usePassiveOneShotLocation()) return; | |
146 | |
147 assert !mIsRunning; | |
148 mIsRunning = true; | |
149 | |
150 // We're running on the main thread. The C++ side is responsible to | |
151 // bounce notifications to the Geolocation thread as they arrive in the mainLooper. | |
152 try { | |
153 Criteria criteria = new Criteria(); | |
154 mLocationManager.requestLocationUpdates(0, 0, criteria, this, | |
155 ThreadUtils.getUiThreadLooper()); | |
156 if (mIsGpsEnabled) { | |
157 criteria.setAccuracy(Criteria.ACCURACY_FINE); | |
158 mLocationManager.requestLocationUpdates(0, 0, criteria, this , | |
159 ThreadUtils.getUiThreadLooper()); | |
160 } | |
161 } catch(SecurityException e) { | |
162 Log.e(TAG, "Caught security exception registering for location u pdates from " + | |
163 "system. This should only happen in DumpRenderTree."); | |
164 } catch(IllegalArgumentException e) { | |
165 Log.e(TAG, "Caught IllegalArgumentException registering for loca tion updates."); | |
166 } | |
167 } | |
168 | |
169 /** | |
170 * Unregisters this object from the location service. | |
171 */ | |
172 private void unregisterFromLocationUpdates() { | |
173 if (mIsRunning) { | |
174 mIsRunning = false; | |
175 mLocationManager.removeUpdates(this); | |
176 } | |
177 } | |
178 | |
179 private boolean usePassiveOneShotLocation() { | |
180 if (!isOnlyPassiveLocationProviderEnabled()) return false; | |
181 | |
182 // Do not request a location update if the only available location p rovider is | |
183 // the passive one. Make use of the last known location and call | |
184 // onLocationChanged directly. | |
185 final Location location = mLocationManager.getLastKnownLocation( | |
186 LocationManager.PASSIVE_PROVIDER); | |
187 if (location != null) { | |
188 ThreadUtils.runOnUiThread(new Runnable() { | |
189 @Override | |
190 public void run() { | |
191 updateNewLocation(location); | |
192 } | |
193 }); | |
194 } | |
195 return true; | |
196 } | |
197 | |
198 /* | |
199 * Checks if the passive location provider is the only provider availabl e | |
200 * in the system. | |
201 */ | |
202 private boolean isOnlyPassiveLocationProviderEnabled() { | |
203 List<String> providers = mLocationManager.getProviders(true); | |
204 return providers != null && providers.size() == 1 | |
205 && providers.get(0).equals(LocationManager.PASSIVE_PROVIDER) ; | |
206 } | |
207 } | |
208 | 30 |
209 // Delegate handling the real work in the main thread. | 31 // Delegate handling the real work in the main thread. |
210 private LocationProviderImpl mImpl; | 32 private LocationProviderFactory.LocationProviderImpl mImpl; |
211 | 33 |
212 private LocationProvider(Context context) { | 34 private LocationProvider(Context context) { |
213 mImpl = new LocationProviderImpl(context); | 35 mImpl = LocationProviderFactory.get(context); |
214 } | 36 } |
215 | 37 |
216 @CalledByNative | 38 @CalledByNative |
217 static LocationProvider create(Context context) { | 39 static LocationProvider create(Context context) { |
218 return new LocationProvider(context); | 40 return new LocationProvider(context); |
219 } | 41 } |
220 | 42 |
221 /** | 43 /** |
222 * Start listening for location updates until we're told to quit. May be | 44 * Start listening for location updates until we're told to quit. May be |
223 * called in any thread. | 45 * called in any thread. |
(...skipping 28 matching lines...) Expand all Loading... | |
252 /** | 74 /** |
253 * Returns true if we are currently listening for location updates, false if not. | 75 * Returns true if we are currently listening for location updates, false if not. |
254 * Must be called only in the UI thread. | 76 * Must be called only in the UI thread. |
255 */ | 77 */ |
256 public boolean isRunning() { | 78 public boolean isRunning() { |
257 assert ThreadUtils.runningOnUiThread(); | 79 assert ThreadUtils.runningOnUiThread(); |
258 return mImpl.isRunning(); | 80 return mImpl.isRunning(); |
259 } | 81 } |
260 | 82 |
261 // Native functions | 83 // Native functions |
262 public static native void nativeNewLocationAvailable( | 84 public static native void nativeNewLocationAvailable( |
bulach
2013/12/11 15:48:39
just realized these should've been private...
benm (inactive)
2013/12/11 20:08:51
OK, made them private but added public static meth
| |
263 double latitude, double longitude, double timeStamp, | 85 double latitude, double longitude, double timeStamp, |
264 boolean hasAltitude, double altitude, | 86 boolean hasAltitude, double altitude, |
265 boolean hasAccuracy, double accuracy, | 87 boolean hasAccuracy, double accuracy, |
266 boolean hasHeading, double heading, | 88 boolean hasHeading, double heading, |
267 boolean hasSpeed, double speed); | 89 boolean hasSpeed, double speed); |
268 public static native void nativeNewErrorAvailable(String message); | 90 public static native void nativeNewErrorAvailable(String message); |
269 } | 91 } |
OLD | NEW |