OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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.device.geolocation; | 5 package org.chromium.device.geolocation; |
6 | 6 |
7 import android.content.Context; | 7 import android.content.Context; |
8 import android.location.Criteria; | 8 import android.location.Criteria; |
9 import android.location.Location; | 9 import android.location.Location; |
10 import android.location.LocationListener; | 10 import android.location.LocationListener; |
(...skipping 15 matching lines...) Expand all Loading... |
26 | 26 |
27 /** | 27 /** |
28 * LocationProviderFactory.get() returns an instance of this interface. | 28 * LocationProviderFactory.get() returns an instance of this interface. |
29 */ | 29 */ |
30 public interface LocationProvider { | 30 public interface LocationProvider { |
31 public void start(boolean enableHighAccuracy); | 31 public void start(boolean enableHighAccuracy); |
32 public void stop(); | 32 public void stop(); |
33 public boolean isRunning(); | 33 public boolean isRunning(); |
34 } | 34 } |
35 | 35 |
36 private LocationProviderFactory() { | 36 private LocationProviderFactory() {} |
37 } | |
38 | 37 |
39 @VisibleForTesting | 38 @VisibleForTesting |
40 public static void setLocationProviderImpl(LocationProviderFactory.LocationP
rovider provider) { | 39 public static void setLocationProviderImpl(LocationProviderFactory.LocationP
rovider provider) { |
41 assert sProviderImpl == null; | 40 assert sProviderImpl == null; |
42 sProviderImpl = provider; | 41 sProviderImpl = provider; |
43 } | 42 } |
44 | 43 |
45 public static LocationProvider get(Context context) { | 44 public static LocationProvider get(Context context) { |
46 if (sProviderImpl == null) { | 45 if (sProviderImpl == null) { |
47 sProviderImpl = new LocationProviderImpl(context); | 46 sProviderImpl = new LocationProviderImpl(context); |
48 } | 47 } |
49 return sProviderImpl; | 48 return sProviderImpl; |
50 } | 49 } |
51 | 50 |
52 /** | 51 /** |
53 * This is the core of android location provider. It is a separate class for
clarity | 52 * This is the core of android location provider. It is a separate class for
clarity |
54 * so that it can manage all processing completely in the UI thread. The con
tainer class | 53 * so that it can manage all processing completely in the UI thread. The con
tainer class |
55 * ensures that the start/stop calls into this class are done in the UI thre
ad. | 54 * ensures that the start/stop calls into this class are done in the UI thre
ad. |
56 */ | 55 */ |
57 private static class LocationProviderImpl | 56 private static class LocationProviderImpl |
58 implements LocationListener, LocationProviderFactory.LocationProvide
r { | 57 implements LocationListener, LocationProviderFactory.LocationProvide
r { |
59 | |
60 // Log tag | 58 // Log tag |
61 private static final String TAG = "cr_LocationProvider"; | 59 private static final String TAG = "cr_LocationProvider"; |
62 | 60 |
63 private Context mContext; | 61 private Context mContext; |
64 private LocationManager mLocationManager; | 62 private LocationManager mLocationManager; |
65 private boolean mIsRunning; | 63 private boolean mIsRunning; |
66 | 64 |
67 LocationProviderImpl(Context context) { | 65 LocationProviderImpl(Context context) { |
68 mContext = context; | 66 mContext = context; |
69 } | 67 } |
(...skipping 28 matching lines...) Expand all Loading... |
98 public void onLocationChanged(Location location) { | 96 public void onLocationChanged(Location location) { |
99 // Callbacks from the system location service are queued to this thr
ead, so it's | 97 // Callbacks from the system location service are queued to this thr
ead, so it's |
100 // possible that we receive callbacks after unregistering. At this p
oint, the | 98 // possible that we receive callbacks after unregistering. At this p
oint, the |
101 // native object will no longer exist. | 99 // native object will no longer exist. |
102 if (mIsRunning) { | 100 if (mIsRunning) { |
103 updateNewLocation(location); | 101 updateNewLocation(location); |
104 } | 102 } |
105 } | 103 } |
106 | 104 |
107 private void updateNewLocation(Location location) { | 105 private void updateNewLocation(Location location) { |
108 LocationProviderAdapter.newLocationAvailable( | 106 LocationProviderAdapter.newLocationAvailable(location.getLatitude(), |
109 location.getLatitude(), location.getLongitude(), | 107 location.getLongitude(), location.getTime() / 1000.0, locati
on.hasAltitude(), |
110 location.getTime() / 1000.0, | 108 location.getAltitude(), location.hasAccuracy(), location.get
Accuracy(), |
111 location.hasAltitude(), location.getAltitude(), | 109 location.hasBearing(), location.getBearing(), location.hasSp
eed(), |
112 location.hasAccuracy(), location.getAccuracy(), | 110 location.getSpeed()); |
113 location.hasBearing(), location.getBearing(), | |
114 location.hasSpeed(), location.getSpeed()); | |
115 } | 111 } |
116 | 112 |
117 @Override | 113 @Override |
118 public void onStatusChanged(String provider, int status, Bundle extras)
{ | 114 public void onStatusChanged(String provider, int status, Bundle extras)
{} |
119 } | |
120 | 115 |
121 @Override | 116 @Override |
122 public void onProviderEnabled(String provider) { | 117 public void onProviderEnabled(String provider) {} |
123 } | |
124 | 118 |
125 @Override | 119 @Override |
126 public void onProviderDisabled(String provider) { | 120 public void onProviderDisabled(String provider) {} |
127 } | |
128 | 121 |
129 private void ensureLocationManagerCreated() { | 122 private void ensureLocationManagerCreated() { |
130 if (mLocationManager != null) return; | 123 if (mLocationManager != null) return; |
131 mLocationManager = (LocationManager) mContext.getSystemService( | 124 mLocationManager = |
132 Context.LOCATION_SERVICE); | 125 (LocationManager) mContext.getSystemService(Context.LOCATION
_SERVICE); |
133 if (mLocationManager == null) { | 126 if (mLocationManager == null) { |
134 Log.e(TAG, "Could not get location manager."); | 127 Log.e(TAG, "Could not get location manager."); |
135 } | 128 } |
136 } | 129 } |
137 | 130 |
138 /** | 131 /** |
139 * Registers this object with the location service. | 132 * Registers this object with the location service. |
140 */ | 133 */ |
141 private void registerForLocationUpdates(boolean enableHighAccuracy) { | 134 private void registerForLocationUpdates(boolean enableHighAccuracy) { |
142 ensureLocationManagerCreated(); | 135 ensureLocationManagerCreated(); |
143 if (usePassiveOneShotLocation()) return; | 136 if (usePassiveOneShotLocation()) return; |
144 | 137 |
145 assert !mIsRunning; | 138 assert !mIsRunning; |
146 mIsRunning = true; | 139 mIsRunning = true; |
147 | 140 |
148 // We're running on the main thread. The C++ side is responsible to | 141 // We're running on the main thread. The C++ side is responsible to |
149 // bounce notifications to the Geolocation thread as they arrive in
the mainLooper. | 142 // bounce notifications to the Geolocation thread as they arrive in
the mainLooper. |
150 try { | 143 try { |
151 Criteria criteria = new Criteria(); | 144 Criteria criteria = new Criteria(); |
152 if (enableHighAccuracy) criteria.setAccuracy(Criteria.ACCURACY_F
INE); | 145 if (enableHighAccuracy) criteria.setAccuracy(Criteria.ACCURACY_F
INE); |
153 mLocationManager.requestLocationUpdates(0, 0, criteria, this, | 146 mLocationManager.requestLocationUpdates( |
154 ThreadUtils.getUiThreadLooper()); | 147 0, 0, criteria, this, ThreadUtils.getUiThreadLooper()); |
155 } catch (SecurityException e) { | 148 } catch (SecurityException e) { |
156 Log.e(TAG, "Caught security exception while registering for loca
tion updates " | 149 Log.e(TAG, "Caught security exception while registering for loca
tion updates " |
157 + "from the system. The application does not have suffic
ient geolocation " | 150 + "from the system. The application does not hav
e sufficient " |
158 + "permissions."); | 151 + "geolocation permissions."); |
159 unregisterFromLocationUpdates(); | 152 unregisterFromLocationUpdates(); |
160 // Propagate an error to JavaScript, this can happen in case of
WebView | 153 // Propagate an error to JavaScript, this can happen in case of
WebView |
161 // when the embedding app does not have sufficient permissions. | 154 // when the embedding app does not have sufficient permissions. |
162 LocationProviderAdapter.newErrorAvailable("application does not
have sufficient " | 155 LocationProviderAdapter.newErrorAvailable("application does not
have sufficient " |
163 + "geolocation permissions."); | 156 + "geolocation permissions."); |
164 } catch (IllegalArgumentException e) { | 157 } catch (IllegalArgumentException e) { |
165 Log.e(TAG, "Caught IllegalArgumentException registering for loca
tion updates."); | 158 Log.e(TAG, "Caught IllegalArgumentException registering for loca
tion updates."); |
166 unregisterFromLocationUpdates(); | 159 unregisterFromLocationUpdates(); |
167 assert false; | 160 assert false; |
168 } | 161 } |
169 } | 162 } |
170 | 163 |
171 /** | 164 /** |
172 * Unregisters this object from the location service. | 165 * Unregisters this object from the location service. |
173 */ | 166 */ |
174 private void unregisterFromLocationUpdates() { | 167 private void unregisterFromLocationUpdates() { |
175 if (mIsRunning) { | 168 if (mIsRunning) { |
176 mIsRunning = false; | 169 mIsRunning = false; |
177 mLocationManager.removeUpdates(this); | 170 mLocationManager.removeUpdates(this); |
178 } | 171 } |
179 } | 172 } |
180 | 173 |
181 private boolean usePassiveOneShotLocation() { | 174 private boolean usePassiveOneShotLocation() { |
182 if (!isOnlyPassiveLocationProviderEnabled()) return false; | 175 if (!isOnlyPassiveLocationProviderEnabled()) return false; |
183 | 176 |
184 // Do not request a location update if the only available location p
rovider is | 177 // Do not request a location update if the only available location p
rovider is |
185 // the passive one. Make use of the last known location and call | 178 // the passive one. Make use of the last known location and call |
186 // onLocationChanged directly. | 179 // onLocationChanged directly. |
187 final Location location = mLocationManager.getLastKnownLocation( | 180 final Location location = |
188 LocationManager.PASSIVE_PROVIDER); | 181 mLocationManager.getLastKnownLocation(LocationManager.PASSIV
E_PROVIDER); |
189 if (location != null) { | 182 if (location != null) { |
190 ThreadUtils.runOnUiThread(new Runnable() { | 183 ThreadUtils.runOnUiThread(new Runnable() { |
191 @Override | 184 @Override |
192 public void run() { | 185 public void run() { |
193 updateNewLocation(location); | 186 updateNewLocation(location); |
194 } | 187 } |
195 }); | 188 }); |
196 } | 189 } |
197 return true; | 190 return true; |
198 } | 191 } |
199 | 192 |
200 /* | 193 /* |
201 * Checks if the passive location provider is the only provider availabl
e | 194 * Checks if the passive location provider is the only provider availabl
e |
202 * in the system. | 195 * in the system. |
203 */ | 196 */ |
204 private boolean isOnlyPassiveLocationProviderEnabled() { | 197 private boolean isOnlyPassiveLocationProviderEnabled() { |
205 List<String> providers = mLocationManager.getProviders(true); | 198 List<String> providers = mLocationManager.getProviders(true); |
206 return providers != null && providers.size() == 1 | 199 return providers != null && providers.size() == 1 |
207 && providers.get(0).equals(LocationManager.PASSIVE_PROVIDER)
; | 200 && providers.get(0).equals(LocationManager.PASSIVE_PROVIDER)
; |
208 } | 201 } |
209 } | 202 } |
210 } | 203 } |
211 | |
212 | |
OLD | NEW |