Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: content/public/android/java/src/org/chromium/content/browser/LocationProvider.java

Issue 65273002: Add a mechanism to pause and resume geolocation requests. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: remove unsused CVC.isGeolocationActiveForTest API Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698