From 843ef36f7b96cc19ea7d2996b7c8661b41ec3452 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Queru Date: Wed, 20 May 2009 11:28:04 -0700 Subject: donut snapshot --- .../android/location/DummyLocationProvider.java | 168 ----- location/java/android/location/Geocoder.java | 16 +- location/java/android/location/GpsStatus.java | 2 +- .../java/android/location/IGeocodeProvider.aidl | 35 + .../java/android/location/IGpsStatusProvider.aidl | 29 + .../java/android/location/ILocationCollector.aidl | 36 ++ .../java/android/location/ILocationManager.aidl | 18 +- .../java/android/location/ILocationProvider.aidl | 47 ++ .../java/android/location/LocationManager.java | 105 ++- .../java/android/location/LocationProvider.java | 4 +- .../android/location/LocationProviderImpl.java | 261 -------- .../com/android/internal/location/CellState.java | 292 --------- .../internal/location/DummyLocationProvider.java | 170 +++++ .../internal/location/GpsLocationProvider.java | 489 +++++++++----- .../internal/location/GpsXtraDownloader.java | 10 +- .../internal/location/ILocationCollector.java | 73 --- .../internal/location/INetworkLocationManager.java | 37 -- .../location/INetworkLocationProvider.java | 95 --- .../internal/location/LocationProviderProxy.java | 251 +++++++ .../android/internal/location/MockProvider.java | 195 ++++++ .../android/internal/location/TrackProvider.java | 720 --------------------- 21 files changed, 1223 insertions(+), 1830 deletions(-) delete mode 100644 location/java/android/location/DummyLocationProvider.java create mode 100644 location/java/android/location/IGeocodeProvider.aidl create mode 100644 location/java/android/location/IGpsStatusProvider.aidl create mode 100644 location/java/android/location/ILocationCollector.aidl create mode 100644 location/java/android/location/ILocationProvider.aidl delete mode 100644 location/java/android/location/LocationProviderImpl.java delete mode 100644 location/java/com/android/internal/location/CellState.java create mode 100644 location/java/com/android/internal/location/DummyLocationProvider.java delete mode 100644 location/java/com/android/internal/location/ILocationCollector.java delete mode 100644 location/java/com/android/internal/location/INetworkLocationManager.java delete mode 100644 location/java/com/android/internal/location/INetworkLocationProvider.java create mode 100644 location/java/com/android/internal/location/LocationProviderProxy.java create mode 100644 location/java/com/android/internal/location/MockProvider.java delete mode 100644 location/java/com/android/internal/location/TrackProvider.java (limited to 'location/java') diff --git a/location/java/android/location/DummyLocationProvider.java b/location/java/android/location/DummyLocationProvider.java deleted file mode 100644 index e1cd4e9..0000000 --- a/location/java/android/location/DummyLocationProvider.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.location; - -/** - * A stub implementation of LocationProvider used by LocationManager. - * A DummyLocationProvider may be queried to determine the properties - * of the provider whcih it shadows, but does not actually provide location - * data. - * - * {@hide} - */ -class DummyLocationProvider extends LocationProvider { - - private static final String TAG = "DummyLocationProvider"; - - String mName; - boolean mRequiresNetwork; - boolean mRequiresSatellite; - boolean mRequiresCell; - boolean mHasMonetaryCost; - boolean mSupportsAltitude; - boolean mSupportsSpeed; - boolean mSupportsBearing; - int mPowerRequirement; - int mAccuracy; - - /* package */ DummyLocationProvider(String name) { - super(name); - } - - public void setRequiresNetwork(boolean requiresNetwork) { - mRequiresNetwork = requiresNetwork; - } - - public void setRequiresSatellite(boolean requiresSatellite) { - mRequiresSatellite = requiresSatellite; - } - - public void setRequiresCell(boolean requiresCell) { - mRequiresCell = requiresCell; - } - - public void setHasMonetaryCost(boolean hasMonetaryCost) { - mHasMonetaryCost = hasMonetaryCost; - } - - public void setSupportsAltitude(boolean supportsAltitude) { - mSupportsAltitude = supportsAltitude; - } - - public void setSupportsSpeed(boolean supportsSpeed) { - mSupportsSpeed = supportsSpeed; - } - - public void setSupportsBearing(boolean supportsBearing) { - mSupportsBearing = supportsBearing; - } - - public void setPowerRequirement(int powerRequirement) { - mPowerRequirement = powerRequirement; - } - - public void setAccuracy(int accuracy) { - mAccuracy = accuracy; - } - - /** - * Returns true if the provider requires access to a - * data network (e.g., the Internet), false otherwise. - */ - public boolean requiresNetwork() { - return mRequiresNetwork; - } - - /** - * Returns true if the provider requires access to a - * satellite-based positioning system (e.g., GPS), false - * otherwise. - */ - public boolean requiresSatellite() { - return mRequiresSatellite; - } - - /** - * Returns true if the provider requires access to an appropriate - * cellular network (e.g., to make use of cell tower IDs), false - * otherwise. - */ - public boolean requiresCell() { - return mRequiresCell; - } - - /** - * Returns true if the use of this provider may result in a - * monetary charge to the user, false if use is free. It is up to - * each provider to give accurate information. - */ - public boolean hasMonetaryCost() { - return mHasMonetaryCost; - } - - /** - * Returns true if the provider is able to provide altitude - * information, false otherwise. A provider that reports altitude - * under most circumstances but may occassionally not report it - * should return true. - */ - public boolean supportsAltitude() { - return mSupportsAltitude; - } - - /** - * Returns true if the provider is able to provide speed - * information, false otherwise. A provider that reports speed - * under most circumstances but may occassionally not report it - * should return true. - */ - public boolean supportsSpeed() { - return mSupportsSpeed; - } - - /** - * Returns true if the provider is able to provide bearing - * information, false otherwise. A provider that reports bearing - * under most circumstances but may occassionally not report it - * should return true. - */ - public boolean supportsBearing() { - return mSupportsBearing; - } - - /** - * Returns the power requirement for this provider. - * - * @return the power requirement for this provider, as one of the - * constants Criteria.POWER_REQUIREMENT_*. - */ - public int getPowerRequirement() { - return mPowerRequirement; - } - - /** - * Returns a constant describing the horizontal accuracy returned - * by this provider. - * - * @return the horizontal accuracy for this provider, as one of the - * constants Criteria.ACCURACY_*. - */ - public int getAccuracy() { - return mAccuracy; - } -} - diff --git a/location/java/android/location/Geocoder.java b/location/java/android/location/Geocoder.java index 709ad23..53e46b7 100644 --- a/location/java/android/location/Geocoder.java +++ b/location/java/android/location/Geocoder.java @@ -36,7 +36,11 @@ import java.util.List; * coordinate into a (partial) address. The amount of detail in a * reverse geocoded location description may vary, for example one * might contain the full street address of the closest building, while - * another might contain only a city name and postal code. + * another might contain only a city name and postal code. + * + * The Geocoder class requires a backend service that is not included in + * the core android framework. The Geocoder query methods will return an + * empty list if there no backend service in the platform. */ public final class Geocoder { private static final String TAG = "Geocoder"; @@ -94,8 +98,8 @@ public final class Geocoder { * @param longitude the longitude a point for the search * @param maxResults max number of addresses to return. Smaller numbers (1 to 5) are recommended * - * @return a list of Address objects or null if no matches were - * found. + * @return a list of Address objects. Returns null or empty list if no matches were + * found or there is no backend service available. * * @throws IllegalArgumentException if latitude is * less than -90 or greater than 90 @@ -143,7 +147,8 @@ public final class Geocoder { * @param locationName a user-supplied description of a location * @param maxResults max number of results to return. Smaller numbers (1 to 5) are recommended * - * @return a list of Address objects or null if no matches were found. + * @return a list of Address objects. Returns null or empty list if no matches were + * found or there is no backend service available. * * @throws IllegalArgumentException if locationName is null * @throws IOException if the network is unavailable or any other @@ -192,7 +197,8 @@ public final class Geocoder { * @param upperRightLatitude the latitude of the upper right corner of the bounding box * @param upperRightLongitude the longitude of the upper right corner of the bounding box * - * @return a list of Address objects or null if no matches were found. + * @return a list of Address objects. Returns null or empty list if no matches were + * found or there is no backend service available. * * @throws IllegalArgumentException if locationName is null * @throws IllegalArgumentException if any latitude is diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java index a40b1fb..2cda7fa 100644 --- a/location/java/android/location/GpsStatus.java +++ b/location/java/android/location/GpsStatus.java @@ -25,7 +25,7 @@ import java.util.NoSuchElementException; * This class is used in conjunction with the {@link Listener} interface. */ public final class GpsStatus { - private static final int NUM_SATELLITES = 32; + private static final int NUM_SATELLITES = 255; /* These package private values are modified by the LocationManager class */ private int mTimeToFirstFix; diff --git a/location/java/android/location/IGeocodeProvider.aidl b/location/java/android/location/IGeocodeProvider.aidl new file mode 100644 index 0000000..e79e8d2 --- /dev/null +++ b/location/java/android/location/IGeocodeProvider.aidl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.location; + +import android.location.Address; + +/** + * An interface for location providers implementing the Geocoder services. + * + * {@hide} + */ +interface IGeocodeProvider { + + String getFromLocation(double latitude, double longitude, int maxResults, + String language, String country, String variant, String appName, out List
addrs); + + String getFromLocationName(String locationName, + double lowerLeftLatitude, double lowerLeftLongitude, + double upperRightLatitude, double upperRightLongitude, int maxResults, + String language, String country, String variant, String appName, out List
addrs); +} diff --git a/location/java/android/location/IGpsStatusProvider.aidl b/location/java/android/location/IGpsStatusProvider.aidl new file mode 100644 index 0000000..cf277c8 --- /dev/null +++ b/location/java/android/location/IGpsStatusProvider.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.location; + +import android.location.IGpsStatusListener; + +/** + * An interface for location providers that provide GPS status information. + * + * {@hide} + */ +interface IGpsStatusProvider { + void addGpsStatusListener(IGpsStatusListener listener); + void removeGpsStatusListener(IGpsStatusListener listener); +} diff --git a/location/java/android/location/ILocationCollector.aidl b/location/java/android/location/ILocationCollector.aidl new file mode 100644 index 0000000..b2e1796 --- /dev/null +++ b/location/java/android/location/ILocationCollector.aidl @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.location; + +import android.location.Location; + +/** + * Listens for GPS and cell/wifi changes and anonymously uploads to server + * for improving quality of service of NetworkLocationProvider. + * This service is only enabled when the user has enabled the + * network location provider. + * + * {@hide} + */ +oneway interface ILocationCollector { + /** + * Updates GPS location if collection is enabled + * + * @param location location object + */ + void updateLocation(in Location location); +} diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index 69c404a..2c214c9 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -18,8 +18,11 @@ package android.location; import android.app.PendingIntent; import android.location.Address; +import android.location.IGeocodeProvider; import android.location.IGpsStatusListener; +import android.location.ILocationCollector; import android.location.ILocationListener; +import android.location.ILocationProvider; import android.location.Location; import android.os.Bundle; @@ -33,8 +36,6 @@ interface ILocationManager List getAllProviders(); List getProviders(boolean enabledOnly); - void updateProviders(); - void requestLocationUpdates(String provider, long minTime, float minDistance, in ILocationListener listener); void requestLocationUpdatesPI(String provider, long minTime, float minDistance, @@ -44,7 +45,10 @@ interface ILocationManager boolean addGpsStatusListener(IGpsStatusListener listener); void removeGpsStatusListener(IGpsStatusListener listener); - + + // for reporting callback completion + void locationCallbackFinished(ILocationListener listener); + boolean sendExtraCommand(String provider, String command, inout Bundle extras); void addProximityAlert(double latitude, double longitude, float distance, @@ -56,6 +60,9 @@ interface ILocationManager Location getLastKnownLocation(String provider); + /* used by location providers to tell the location manager when it has a new location */ + void reportLocation(in Location location); + String getFromLocation(double latitude, double longitude, int maxResults, String language, String country, String variant, String appName, out List
addrs); String getFromLocationName(String locationName, @@ -73,4 +80,9 @@ interface ILocationManager void clearTestProviderEnabled(String provider); void setTestProviderStatus(String provider, int status, in Bundle extras, long updateTime); void clearTestProviderStatus(String provider); + + /* for installing external Location Providers */ + void installLocationProvider(String name, ILocationProvider provider); + void installLocationCollector(ILocationCollector collector); + void installGeocodeProvider(IGeocodeProvider provider); } diff --git a/location/java/android/location/ILocationProvider.aidl b/location/java/android/location/ILocationProvider.aidl new file mode 100644 index 0000000..6c23f83 --- /dev/null +++ b/location/java/android/location/ILocationProvider.aidl @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.location; + +import android.os.Bundle; + +/** + * Binder interface for location providers. + * + * {@hide} + */ +interface ILocationProvider { + boolean requiresNetwork(); + boolean requiresSatellite(); + boolean requiresCell(); + boolean hasMonetaryCost(); + boolean supportsAltitude(); + boolean supportsSpeed(); + boolean supportsBearing(); + int getPowerRequirement(); + int getAccuracy(); + void enable(); + void disable(); + boolean isEnabled(); + int getStatus(out Bundle extras); + long getStatusUpdateTime(); + void enableLocationTracking(boolean enable); + void setMinTime(long minTime); + void updateNetworkState(int state); + boolean sendExtraCommand(String command, inout Bundle extras); + void addListener(int uid); + void removeListener(int uid); +} diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 022ee25..872838c 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -26,6 +26,8 @@ import android.os.Message; import android.util.Config; import android.util.Log; +import com.android.internal.location.DummyLocationProvider; + import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -101,9 +103,6 @@ public class LocationManager { */ public static final String KEY_LOCATION_CHANGED = "location"; - /** @hide -- does this belong here? */ - public static final String PROVIDER_DIR = "/data/location"; - /** @hide */ public static final String SYSTEM_DIR = "/data/system/location"; @@ -194,6 +193,11 @@ public class LocationManager { mListener.onProviderDisabled((String) msg.obj); break; } + try { + mService.locationCallbackFinished(this); + } catch (RemoteException e) { + Log.e(TAG, "locationCallbackFinished: RemoteException", e); + } } } /** @@ -313,20 +317,6 @@ public class LocationManager { } /** - * Propagates the enabled/disabled state of the providers from the system - * settings to the providers themselves. - * - * {@hide} - */ - public void updateProviders() { - try { - mService.updateProviders(); - } catch (RemoteException ex) { - Log.e(TAG, "updateProviders: RemoteException", ex); - } - } - - /** * Returns the next looser power requirement, in the sequence: * * POWER_LOW -> POWER_MEDIUM -> POWER_HIGH -> NO_REQUIREMENT @@ -1265,4 +1255,85 @@ public class LocationManager { return false; } } + + /** + * Installs a location provider. + * + * @param name of the location provider + * @param provider Binder interface for the location provider + * + * @return true if the command succeeds. + * + * Requires the android.permission.INSTALL_LOCATION_PROVIDER permission. + * + * {@hide} + */ + public boolean installLocationProvider(String name, ILocationProvider provider) { + try { + mService.installLocationProvider(name, provider); + return true; + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in installLocationProvider: ", e); + return false; + } + } + + /** + * Installs a location collector. + * + * @param provider Binder interface for the location collector + * + * @return true if the command succeeds. + * + * Requires the android.permission.INSTALL_LOCATION_COLLECTOR permission. + * + * {@hide} + */ + public boolean installLocationCollector(ILocationCollector collector) { + try { + mService.installLocationCollector(collector); + return true; + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in setLocationCollector: ", e); + return false; + } + } + + /** + * Installs a geocoder server. + * + * @param provider Binder interface for the geocoder provider + * + * @return true if the command succeeds. + * + * Requires the android.permission.INSTALL_LOCATION_PROVIDER permission. + * + * {@hide} + */ + public boolean installGeocodeProvider(IGeocodeProvider provider) { + try { + mService.installGeocodeProvider(provider); + return true; + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in setGeocodeProvider: ", e); + return false; + } + } + + /** + * Used by location providers to report new locations. + * + * @param location new Location to report + * + * Requires the android.permission.INSTALL_LOCATION_PROVIDER permission. + * + * {@hide} + */ + public void reportLocation(Location location) { + try { + mService.reportLocation(location); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in reportLocation: ", e); + } + } } diff --git a/location/java/android/location/LocationProvider.java b/location/java/android/location/LocationProvider.java index b1670d5..3faba58 100644 --- a/location/java/android/location/LocationProvider.java +++ b/location/java/android/location/LocationProvider.java @@ -47,8 +47,10 @@ public abstract class LocationProvider { * consist only of the characters [a-zA-Z0-9]. * * @throws IllegalArgumentException if name contains an illegal character + * + * {@hide} */ - LocationProvider(String name) { + public LocationProvider(String name) { if (name.matches(BAD_CHARS_REGEX)) { throw new IllegalArgumentException("name " + name + " contains an illegal character"); diff --git a/location/java/android/location/LocationProviderImpl.java b/location/java/android/location/LocationProviderImpl.java deleted file mode 100644 index 0962992..0000000 --- a/location/java/android/location/LocationProviderImpl.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.location; - -import com.android.internal.location.CellState; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -import android.os.Bundle; -import android.util.Config; -import android.util.Log; - -/** - * An abstract superclass for location provider implementations. - * Location provider implementations are typically instantiated by the - * location manager service in the system process, and location - * information is made available to implementations via the manager. - * - * {@hide} - */ -public abstract class LocationProviderImpl extends LocationProvider { - private static final String TAG = "LocationProviderImpl"; - - private static ArrayList sProviders = - new ArrayList(); - private static HashMap sProvidersByName - = new HashMap(); - - private boolean mLocationTracking = false; - private long mMinTime = 0; - - protected LocationProviderImpl(String name) { - super(name); - } - - public static void addProvider(LocationProviderImpl provider) { - sProviders.add(provider); - sProvidersByName.put(provider.getName(), provider); - } - - public static void removeProvider(LocationProviderImpl provider) { - sProviders.remove(provider); - sProvidersByName.remove(provider.getName()); - } - - public static List getProviders() { - return new ArrayList(sProviders); - } - - public static LocationProviderImpl getProvider(String name) { - return sProvidersByName.get(name); - } - - public static LocationProviderImpl loadFromClass(File classFile) { - if (!classFile.exists()) { - return null; - } - if (Config.LOGD) { - Log.d(TAG, "Loading class specifier file " + classFile.getPath()); - } - String className = null; - try { - BufferedReader br = - new BufferedReader(new FileReader(classFile), 8192); - className = br.readLine(); - br.close(); - Class providerClass = Class.forName(className); - if (Config.LOGD) { - Log.d(TAG, "Loading provider class " + providerClass.getName()); - } - LocationProviderImpl provider = - (LocationProviderImpl) providerClass.newInstance(); - if (Config.LOGD) { - Log.d(TAG, "Got provider instance " + provider); - } - - return provider; - } catch (IOException ioe) { - Log.e(TAG, "IOException loading config file " + - classFile.getPath(), ioe); - } catch (IllegalAccessException iae) { - Log.e(TAG, "IllegalAccessException loading class " + - className, iae); - } catch (InstantiationException ie) { - Log.e(TAG, "InstantiationException loading class " + - className, ie); - } catch (ClassNotFoundException cnfe) { - Log.e(TAG, "ClassNotFoundException loading class " + - className, cnfe); - } catch (ClassCastException cce) { - Log.e(TAG, "ClassCastException loading class " + - className, cce); - } - return null; - } - - /** - * Enables this provider. When enabled, calls to {@link #getStatus()} - * and {@link #getLocation} must be handled. Hardware may be started up - * when the provider is enabled. - */ - public abstract void enable(); - - /** - * Disables this provider. When disabled, calls to {@link #getStatus()} - * and {@link #getLocation} need not be handled. Hardware may be shut - * down while the provider is disabled. - */ - public abstract void disable(); - - /** - * Returns true if this provider is enabled, false otherwise; - */ - public abstract boolean isEnabled(); - - /** - * Returns a information on the status of this provider. - * {@link #OUT_OF_SERVICE} is returned if the provider is - * out of service, and this is not expected to change in the near - * future; {@link #TEMPORARILY_UNAVAILABLE} is returned if - * the provider is temporarily unavailable but is expected to be - * available shortly; and {@link #AVAILABLE} is returned - * if the provider is currently available. - */ - public int getStatus() { - return getStatus(null); - } - - /** - * Returns a information on the status of this provider. - * {@link #OUT_OF_SERVICE} is returned if the provider is - * out of service, and this is not expected to change in the near - * future; {@link #TEMPORARILY_UNAVAILABLE} is returned if - * the provider is temporarily unavailable but is expected to be - * available shortly; and {@link #AVAILABLE} is returned - * if the provider is currently available. - * - *

If extras is non-null, additional status information may be - * added to it in the form of provider-specific key/value pairs. - */ - public abstract int getStatus(Bundle extras); - - /** - * Returns the time at which the status was last updated. It is the - * responsibility of the provider to appropriately set this value - * using {@link android.os.SystemClock.elapsedRealtime()} each time - * there is a status update that it wishes to broadcast to all its - * listeners. The provider should be careful not to broadcast - * the same status again. - * - * @return time of last status update in millis since last reboot - */ - public long getStatusUpdateTime() { - return 0; - } - - /** - * Sets a Location object with the information gathered - * during the most recent fix. - * - * @param l location object to set - * @return true if a location fix is available - */ - public abstract boolean getLocation(Location l); - - /** - * Notifies the location provider that clients are listening for locations. - * Called with enable set to true when the first client is added and - * called with enable set to false when the last client is removed. - * This allows the provider to prepare for receiving locations, - * and to shut down when no clients are remaining. - * - * @param enable true if location tracking should be enabled. - */ - public void enableLocationTracking(boolean enable) { - mLocationTracking = enable; - } - - /** - * Returns true if the provider has any listeners - * - * @return true if provider is being tracked - */ - public boolean isLocationTracking() { - return mLocationTracking; - } - - /** - * Notifies the location provider of the smallest minimum time between updates amongst - * all clients that are listening for locations. This allows the provider to reduce - * the frequency of updates to match the requested frequency. - * - * @param minTime the smallest minTime value over all listeners for this provider. - */ - public void setMinTime(long minTime) { - mMinTime = minTime; - } - - /** - * Gets the smallest minimum time between updates amongst all the clients listening - * for locations. By default this value is 0 (as frqeuently as possible) - * - * @return the smallest minTime value over all listeners for this provider - */ - public long getMinTime() { - return mMinTime; - } - - /** - * Updates the network state for the given provider. This function must - * be overwritten if {@link #requiresNetwork} returns true. The state is - * {@link #TEMPORARILY_UNAVAILABLE} (disconnected), OR {@link #AVAILABLE} - * (connected or connecting). - * - * @param state data state - */ - public void updateNetworkState(int state) { - } - - /** - * Updates the cell state for the given provider. This function must be - * overwritten if {@link #requiresCell} returns true. - * - * @param state cell state - */ - public void updateCellState(CellState state) { - } - - /** - * Implements addditional location provider specific additional commands. - * - * @param command name of the command to send to the provider. - * @param extras optional arguments for the command (or null). - * The provider may optionally fill the extras Bundle with results from the command. - * - * @return true if the command succeeds. - */ - public boolean sendExtraCommand(String command, Bundle extras) { - return false; - } -} diff --git a/location/java/com/android/internal/location/CellState.java b/location/java/com/android/internal/location/CellState.java deleted file mode 100644 index eb6535e..0000000 --- a/location/java/com/android/internal/location/CellState.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.location; - -import android.telephony.CellLocation; -import android.telephony.TelephonyManager; -import android.telephony.NeighboringCellInfo; -import android.telephony.gsm.GsmCellLocation; -import android.util.Log; - -import com.android.internal.telephony.TelephonyProperties; - -import java.util.List; -import java.util.ArrayList; - -import android.os.SystemProperties; - -/** - * Stores the cell tower state - * - * {@hide} - */ -public class CellState { - - public static String TAG = "CellState"; - - public static int RADIO_TYPE_GPRS = 1; - public static int RADIO_TYPE_CDMA = 2; - public static int RADIO_TYPE_WCDMA = 3; - - private int mCid = -1; - private int mLac = -1; - private int mMcc = -1; - private int mMnc = -1; - private int mHomeMcc = -1; - private int mHomeMnc = -1; - private String mCarrier = null; - private int mRadioType = -1; - private long mTime = 0; - private int mSignalStrength = -1; - - private List mNeighbors; - - public CellState() { - // constructor for invalid cell location - } - - public CellState(TelephonyManager telephonyManager, CellLocation location, int signalStrength) { - GsmCellLocation loc = (GsmCellLocation)location; - mLac = loc.getLac(); // example: 6032 - mCid = loc.getCid(); // example: 31792 - mTime = System.currentTimeMillis(); - - // Get radio type - int radioType = telephonyManager.getNetworkType(); - if (radioType == TelephonyManager.NETWORK_TYPE_GPRS || - radioType == TelephonyManager.NETWORK_TYPE_EDGE) { - mRadioType = RADIO_TYPE_GPRS; - } else if (radioType == TelephonyManager.NETWORK_TYPE_UMTS) { - mRadioType = RADIO_TYPE_WCDMA; - } - - // Get neighboring cells - mNeighbors = new ArrayList(); - List neighboringCells = telephonyManager.getNeighboringCellInfo(); - if (neighboringCells != null) { - for (NeighboringCellInfo n : neighboringCells) { - if (n.getCid() == NeighboringCellInfo.UNKNOWN_CID) { - continue; - } - - if (mRadioType == RADIO_TYPE_WCDMA) { - mNeighbors.add(new NeighborCell(-1, -1, n.getCid(), n.getRssi())); - } else if (mRadioType == RADIO_TYPE_GPRS) { - try { - String hexCidLac = Integer.toHexString(n.getCid()); - int l = hexCidLac.length(); - if (l > 8) { - Log.w(TAG, "Unable to parse 2G Cell \"" + hexCidLac + "\""); - continue; - } - if (l < 8) { - for (int i = 0; i < (8-l); i++) { - hexCidLac = "0" + hexCidLac; - } - } - int lac = Integer.valueOf(hexCidLac.substring(0, 4), 16); - int cid = Integer.valueOf(hexCidLac.substring(4), 16); - mNeighbors.add(new NeighborCell(cid, lac, -1, n.getRssi())); - - } catch (Exception e) { - Log.e(TAG, "Error parsing 2G Cell \"" + n.getCid() + "\"", e); - } - } - } - } - - // Get MCC/MNC - String operator = telephonyManager.getNetworkOperator(); - if (operator != null && !operator.equals("")) { - // Use a try/catch block to detect index out of bounds or number format exceptions. - // If an error occurs, both mMcc and mMnc will be equal to -1. - try { - String mcc = operator.substring(0, 3); - String mnc = operator.substring(3); - int mccTmp = Integer.parseInt(mcc); - int mncTmp = Integer.parseInt(mnc); - - // Parsing succeeded, update the instance variables together - mMcc = mccTmp; - mMnc = mncTmp; - } catch (Exception e) { - Log.e(TAG, "Error parsing MCC/MNC from operator \"" + operator + "\"", e); - } - } - - // Get Home MCC/MNC - String homeOperator = telephonyManager.getSimOperator(); - if (homeOperator != null && !homeOperator.equals("")) { - // Use a try/catch block to detect index out of bounds or number format exceptions. - // If an error occurs, both mHomeMcc and mHomeMnc will be equal to -1. - try { - String mcc = homeOperator.substring(0, 3); - String mnc = homeOperator.substring(3); - int mccTmp = Integer.parseInt(mcc); - int mncTmp = Integer.parseInt(mnc); - - // Parsing succeeded, update the instance variables together - mHomeMcc = mccTmp; - mHomeMnc = mncTmp; - } catch (Exception e) { - Log.e(TAG, "Error parsing MCC/MNC from home operator \"" + homeOperator + "\"", e); - } - } - - // Get Carrier - String carrier = telephonyManager.getNetworkOperatorName(); - if (carrier != null && !carrier.equals("")) { - mCarrier = carrier; - } - - // Initial signal strength - mSignalStrength = signalStrength; - - if (Log.isLoggable(TAG, Log.VERBOSE)) { - String neighbors = "["; - for (NeighborCell n : mNeighbors) { - neighbors += n.toString() + ","; - } - neighbors += "]"; - Log.d(TAG, "CellState(): " + mLac +"," + mCid + "," + mMnc +"," + mMcc + "," + - mHomeMcc + "," + mHomeMnc + "," + mCarrier + "," + mRadioType + "," + - mSignalStrength + "," + neighbors); - } - } - - public void updateRadioType(int radioType) { - mRadioType = radioType; - - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.d(TAG, "updateRadioType(): " + mLac +"," + mCid + "," + mMnc +"," + mMcc + "," + - mHomeMcc + "," + mHomeMnc + "," + mCarrier + "," + mRadioType + "," + - mSignalStrength); - } - } - - public void updateSignalStrength(int signalStrength) { - mSignalStrength = signalStrength; - - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.d(TAG, "updateSignal(): " + mLac +"," + mCid + "," + mMnc +"," + mMcc + "," + - mHomeMcc + "," + mHomeMnc + "," + mCarrier + "," + mRadioType + "," + - mSignalStrength); - } - } - - public int getCid() { - return mCid; - } - - public int getLac() { - return mLac; - } - - public int getMcc() { - return mMcc; - } - - public int getMnc() { - return mMnc; - } - - public int getHomeMcc() { - return mHomeMcc; - } - - public void setHomeMcc(int homeMcc) { - this.mHomeMcc = homeMcc; - } - - public int getHomeMnc() { - return mHomeMnc; - } - - public void setHomeMnc(int homeMnc) { - this.mHomeMnc = homeMnc; - } - - public String getCarrier() { - return mCarrier; - } - - public void setCarrier(String carrier) { - this.mCarrier = carrier; - } - - public int getRadioType() { - return mRadioType; - } - - public long getTime() { - return mTime; - } - - public int getSignalStrength() { - return mSignalStrength; - } - - public List getNeighbors() { - return mNeighbors; - } - - public boolean equals(CellState other) { - return (mCid == other.mCid && mLac == other.mLac); - } - - public boolean isValid() { - return (mCid != -1 && mLac != -1); - } - - public static class NeighborCell { - private int mCid = -1; - private int mLac = -1; - private int mPsc = -1; - private int mRssi = -1; - - NeighborCell(int cid, int lac, int psc, int rssi) { - mCid = cid; - mLac = lac; - mPsc = psc; - mRssi = rssi; - } - - public int getCid() { - return mCid; - } - - public int getLac() { - return mLac; - } - - public int getPsc() { - return mPsc; - } - - public int getRssi() { - return mRssi; - } - - public String toString() { - if (mPsc != -1) { - return String.valueOf(mPsc) + "@" + mRssi; - } else { - return mCid + ":" + mLac + "@" + mRssi; - } - } - } -} diff --git a/location/java/com/android/internal/location/DummyLocationProvider.java b/location/java/com/android/internal/location/DummyLocationProvider.java new file mode 100644 index 0000000..ff5e27b --- /dev/null +++ b/location/java/com/android/internal/location/DummyLocationProvider.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.location; + +import android.location.LocationProvider; + +/** + * A stub implementation of LocationProvider used by LocationManager. + * A DummyLocationProvider may be queried to determine the properties + * of the provider whcih it shadows, but does not actually provide location + * data. + * + * {@hide} + */ +public class DummyLocationProvider extends LocationProvider { + + private static final String TAG = "DummyLocationProvider"; + + String mName; + boolean mRequiresNetwork; + boolean mRequiresSatellite; + boolean mRequiresCell; + boolean mHasMonetaryCost; + boolean mSupportsAltitude; + boolean mSupportsSpeed; + boolean mSupportsBearing; + int mPowerRequirement; + int mAccuracy; + + public DummyLocationProvider(String name) { + super(name); + } + + public void setRequiresNetwork(boolean requiresNetwork) { + mRequiresNetwork = requiresNetwork; + } + + public void setRequiresSatellite(boolean requiresSatellite) { + mRequiresSatellite = requiresSatellite; + } + + public void setRequiresCell(boolean requiresCell) { + mRequiresCell = requiresCell; + } + + public void setHasMonetaryCost(boolean hasMonetaryCost) { + mHasMonetaryCost = hasMonetaryCost; + } + + public void setSupportsAltitude(boolean supportsAltitude) { + mSupportsAltitude = supportsAltitude; + } + + public void setSupportsSpeed(boolean supportsSpeed) { + mSupportsSpeed = supportsSpeed; + } + + public void setSupportsBearing(boolean supportsBearing) { + mSupportsBearing = supportsBearing; + } + + public void setPowerRequirement(int powerRequirement) { + mPowerRequirement = powerRequirement; + } + + public void setAccuracy(int accuracy) { + mAccuracy = accuracy; + } + + /** + * Returns true if the provider requires access to a + * data network (e.g., the Internet), false otherwise. + */ + public boolean requiresNetwork() { + return mRequiresNetwork; + } + + /** + * Returns true if the provider requires access to a + * satellite-based positioning system (e.g., GPS), false + * otherwise. + */ + public boolean requiresSatellite() { + return mRequiresSatellite; + } + + /** + * Returns true if the provider requires access to an appropriate + * cellular network (e.g., to make use of cell tower IDs), false + * otherwise. + */ + public boolean requiresCell() { + return mRequiresCell; + } + + /** + * Returns true if the use of this provider may result in a + * monetary charge to the user, false if use is free. It is up to + * each provider to give accurate information. + */ + public boolean hasMonetaryCost() { + return mHasMonetaryCost; + } + + /** + * Returns true if the provider is able to provide altitude + * information, false otherwise. A provider that reports altitude + * under most circumstances but may occassionally not report it + * should return true. + */ + public boolean supportsAltitude() { + return mSupportsAltitude; + } + + /** + * Returns true if the provider is able to provide speed + * information, false otherwise. A provider that reports speed + * under most circumstances but may occassionally not report it + * should return true. + */ + public boolean supportsSpeed() { + return mSupportsSpeed; + } + + /** + * Returns true if the provider is able to provide bearing + * information, false otherwise. A provider that reports bearing + * under most circumstances but may occassionally not report it + * should return true. + */ + public boolean supportsBearing() { + return mSupportsBearing; + } + + /** + * Returns the power requirement for this provider. + * + * @return the power requirement for this provider, as one of the + * constants Criteria.POWER_REQUIREMENT_*. + */ + public int getPowerRequirement() { + return mPowerRequirement; + } + + /** + * Returns a constant describing the horizontal accuracy returned + * by this provider. + * + * @return the horizontal accuracy for this provider, as one of the + * constants Criteria.ACCURACY_*. + */ + public int getAccuracy() { + return mAccuracy; + } +} + diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java index 887574a..565859c 100644 --- a/location/java/com/android/internal/location/GpsLocationProvider.java +++ b/location/java/com/android/internal/location/GpsLocationProvider.java @@ -16,24 +16,33 @@ package com.android.internal.location; +import android.app.AlarmManager; +import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.location.Criteria; import android.location.IGpsStatusListener; +import android.location.IGpsStatusProvider; +import android.location.ILocationManager; +import android.location.ILocationProvider; import android.location.Location; import android.location.LocationManager; import android.location.LocationProvider; -import android.location.LocationProviderImpl; +import android.net.ConnectivityManager; import android.net.SntpClient; import android.os.Bundle; import android.os.IBinder; +import android.os.PowerManager; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.SystemClock; import android.util.Config; import android.util.Log; +import android.util.SparseIntArray; +import com.android.internal.app.IBatteryStats; import com.android.internal.telephony.Phone; import com.android.internal.telephony.TelephonyIntents; @@ -50,9 +59,12 @@ import java.util.Properties; * * {@hide} */ -public class GpsLocationProvider extends LocationProviderImpl { +public class GpsLocationProvider extends ILocationProvider.Stub { private static final String TAG = "GpsLocationProvider"; + + private static final boolean DEBUG = true; + private static final boolean VERBOSE = false; /** * Broadcast intent action indicating that the GPS has either been @@ -97,6 +109,14 @@ public class GpsLocationProvider extends LocationProviderImpl { private static final int GPS_STATUS_ENGINE_ON = 3; private static final int GPS_STATUS_ENGINE_OFF = 4; + // these need to match GpsApgsStatusValue defines in gps.h + /** AGPS status event values. */ + private static final int GPS_REQUEST_AGPS_DATA_CONN = 1; + private static final int GPS_RELEASE_AGPS_DATA_CONN = 2; + private static final int GPS_AGPS_DATA_CONNECTED = 3; + private static final int GPS_AGPS_DATA_CONN_DONE = 4; + private static final int GPS_AGPS_DATA_CONN_FAILED = 5; + // these need to match GpsLocationFlags enum in gps.h private static final int LOCATION_INVALID = 0; private static final int LOCATION_HAS_LAT_LONG = 1; @@ -104,8 +124,8 @@ public class GpsLocationProvider extends LocationProviderImpl { private static final int LOCATION_HAS_SPEED = 4; private static final int LOCATION_HAS_BEARING = 8; private static final int LOCATION_HAS_ACCURACY = 16; - -// IMPORTANT - the GPS_DELETE_* symbols here must match constants in GpsLocationProvider.java + +// IMPORTANT - the GPS_DELETE_* symbols here must match constants in gps.h private static final int GPS_DELETE_EPHEMERIS = 0x0001; private static final int GPS_DELETE_ALMANAC = 0x0002; private static final int GPS_DELETE_POSITION = 0x0004; @@ -120,23 +140,36 @@ public class GpsLocationProvider extends LocationProviderImpl { private static final int GPS_DELETE_CELLDB_INFO = 0x8000; private static final int GPS_DELETE_ALL = 0xFFFF; + // these need to match AGpsType enum in gps.h + private static final int AGPS_TYPE_SUPL = 1; + private static final int AGPS_TYPE_C2K = 2; + + // for mAGpsDataConnectionState + private static final int AGPS_DATA_CONNECTION_CLOSED = 0; + private static final int AGPS_DATA_CONNECTION_OPENING = 1; + private static final int AGPS_DATA_CONNECTION_OPEN = 2; + private static final String PROPERTIES_FILE = "/etc/gps.conf"; private int mLocationFlags = LOCATION_INVALID; // current status - private int mStatus = TEMPORARILY_UNAVAILABLE; + private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE; // time for last status update private long mStatusUpdateTime = SystemClock.elapsedRealtime(); // turn off GPS fix icon if we haven't received a fix in 10 seconds - private static final long RECENT_FIX_TIMEOUT = 10 * 1000; + private static final long RECENT_FIX_TIMEOUT = 10; + + // number of fixes to receive before disabling GPS + private static final int MIN_FIX_COUNT = 10; + + // stop trying if we do not receive a fix within 60 seconds + private static final int NO_FIX_TIMEOUT = 60; // true if we are enabled private boolean mEnabled; - // true if we are enabled for location updates - private boolean mLocationTracking; // true if we have network connectivity private boolean mNetworkAvailable; @@ -147,6 +180,9 @@ public class GpsLocationProvider extends LocationProviderImpl { // requested frequency of fixes, in seconds private int mFixInterval = 1; + // number of fixes we have received since we started navigating + private int mFixCount; + private int mPositionMode = GPS_POSITION_MODE_STANDALONE; // true if we started navigation @@ -163,7 +199,8 @@ public class GpsLocationProvider extends LocationProviderImpl { private Properties mProperties; private String mNtpServer; - private Context mContext; + private final Context mContext; + private final ILocationManager mLocationManager; private Location mLocation = new Location(LocationManager.GPS_PROVIDER); private Bundle mLocationExtras = new Bundle(); private ArrayList mListeners = new ArrayList(); @@ -173,7 +210,27 @@ public class GpsLocationProvider extends LocationProviderImpl { private String mSuplHost; private int mSuplPort; + private String mC2KHost; + private int mC2KPort; private boolean mSetSuplServer; + private boolean mSetC2KServer; + private String mAGpsApn; + private int mAGpsDataConnectionState; + private final ConnectivityManager mConnMgr; + + // Wakelocks + private final static String WAKELOCK_KEY = "GpsLocationProvider"; + private final PowerManager.WakeLock mWakeLock; + + // Alarms + private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP"; + private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT"; + private final AlarmManager mAlarmManager; + private final PendingIntent mWakeupIntent; + private final PendingIntent mTimeoutIntent; + + private final IBatteryStats mBatteryStats; + private final SparseIntArray mClientUids = new SparseIntArray(); // how often to request NTP time, in milliseconds // current setting 4 hours @@ -182,13 +239,68 @@ public class GpsLocationProvider extends LocationProviderImpl { // current setting - 5 minutes private static final long RETRY_INTERVAL = 5*60*1000; - private ILocationCollector mCollector; + private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() { + public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException { + if (listener == null) { + throw new NullPointerException("listener is null in addGpsStatusListener"); + } + + synchronized(mListeners) { + IBinder binder = listener.asBinder(); + int size = mListeners.size(); + for (int i = 0; i < size; i++) { + Listener test = mListeners.get(i); + if (binder.equals(test.mListener.asBinder())) { + // listener already added + return; + } + } + + Listener l = new Listener(listener); + binder.linkToDeath(l, 0); + mListeners.add(l); + } + } + + public void removeGpsStatusListener(IGpsStatusListener listener) { + if (listener == null) { + throw new NullPointerException("listener is null in addGpsStatusListener"); + } + + synchronized(mListeners) { + IBinder binder = listener.asBinder(); + Listener l = null; + int size = mListeners.size(); + for (int i = 0; i < size && l == null; i++) { + Listener test = mListeners.get(i); + if (binder.equals(test.mListener.asBinder())) { + l = test; + } + } + + if (l != null) { + mListeners.remove(l); + binder.unlinkToDeath(l, 0); + } + } + } + }; + + public IGpsStatusProvider getGpsStatusProvider() { + return mGpsStatusProvider; + } - private class TelephonyBroadcastReceiver extends BroadcastReceiver { + private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); - if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) { + if (action.equals(ALARM_WAKEUP)) { + if (DEBUG) Log.d(TAG, "ALARM_WAKEUP"); + startNavigating(); + } else if (action.equals(ALARM_TIMEOUT)) { + if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT"); + hibernate(); + } else if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) { String state = intent.getStringExtra(Phone.STATE_KEY); String apnName = intent.getStringExtra(Phone.DATA_APN_KEY); String reason = intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY); @@ -196,27 +308,44 @@ public class GpsLocationProvider extends LocationProviderImpl { if (Config.LOGD) { Log.d(TAG, "state: " + state + " apnName: " + apnName + " reason: " + reason); } - if ("CONNECTED".equals(state)) { - native_set_supl_apn(apnName); - } else { - native_set_supl_apn(""); + // FIXME - might not have an APN on CDMA + if ("CONNECTED".equals(state) && apnName != null && apnName.length() > 0) { + mAGpsApn = apnName; + if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) { + native_agps_data_conn_open(mAGpsApn); + mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN; + } } } } - } + }; public static boolean isSupported() { return native_is_supported(); } - public GpsLocationProvider(Context context) { - super(LocationManager.GPS_PROVIDER); + public GpsLocationProvider(Context context, ILocationManager locationManager) { mContext = context; + mLocationManager = locationManager; + + // Create a wake lock + PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY); + + mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); + mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0); + mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0); - TelephonyBroadcastReceiver receiver = new TelephonyBroadcastReceiver(); IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(ALARM_WAKEUP); + intentFilter.addAction(ALARM_TIMEOUT); intentFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); - context.registerReceiver(receiver, intentFilter); + context.registerReceiver(mBroadcastReciever, intentFilter); + + mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); + + // Battery statistics service to be notified when GPS turns on or off + mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo")); mProperties = new Properties(); try { @@ -225,14 +354,26 @@ public class GpsLocationProvider extends LocationProviderImpl { mProperties.load(stream); stream.close(); mNtpServer = mProperties.getProperty("NTP_SERVER", null); + mSuplHost = mProperties.getProperty("SUPL_HOST"); - String suplPortString = mProperties.getProperty("SUPL_PORT"); - if (mSuplHost != null && suplPortString != null) { + String portString = mProperties.getProperty("SUPL_PORT"); + if (mSuplHost != null && portString != null) { try { - mSuplPort = Integer.parseInt(suplPortString); + mSuplPort = Integer.parseInt(portString); mSetSuplServer = true; } catch (NumberFormatException e) { - Log.e(TAG, "unable to parse SUPL_PORT: " + suplPortString); + Log.e(TAG, "unable to parse SUPL_PORT: " + portString); + } + } + + mC2KHost = mProperties.getProperty("C2K_HOST"); + portString = mProperties.getProperty("C2K_PORT"); + if (mC2KHost != null && portString != null) { + try { + mC2KPort = Integer.parseInt(portString); + mSetC2KServer = true; + } catch (NumberFormatException e) { + Log.e(TAG, "unable to parse C2K_PORT: " + portString); } } } catch (IOException e) { @@ -240,19 +381,15 @@ public class GpsLocationProvider extends LocationProviderImpl { } } - public void setLocationCollector(ILocationCollector collector) { - mCollector = collector; - } - /** * Returns true if the provider requires access to a * data network (e.g., the Internet), false otherwise. */ - @Override public boolean requiresNetwork() { // We want updateNetworkState() to get called when the network state changes // for XTRA and NTP time injection support. - return (mNtpServer != null || native_supports_xtra() || mSuplHost != null); + return (mNtpServer != null || native_supports_xtra() || + mSuplHost != null || mC2KHost != null); } public void updateNetworkState(int state) { @@ -273,7 +410,6 @@ public class GpsLocationProvider extends LocationProviderImpl { * satellite-based positioning system (e.g., GPS), false * otherwise. */ - @Override public boolean requiresSatellite() { return true; } @@ -283,7 +419,6 @@ public class GpsLocationProvider extends LocationProviderImpl { * cellular network (e.g., to make use of cell tower IDs), false * otherwise. */ - @Override public boolean requiresCell() { return false; } @@ -293,7 +428,6 @@ public class GpsLocationProvider extends LocationProviderImpl { * monetary charge to the user, false if use is free. It is up to * each provider to give accurate information. */ - @Override public boolean hasMonetaryCost() { return false; } @@ -304,7 +438,6 @@ public class GpsLocationProvider extends LocationProviderImpl { * under most circumstances but may occassionally not report it * should return true. */ - @Override public boolean supportsAltitude() { return true; } @@ -315,7 +448,6 @@ public class GpsLocationProvider extends LocationProviderImpl { * under most circumstances but may occassionally not report it * should return true. */ - @Override public boolean supportsSpeed() { return true; } @@ -326,7 +458,6 @@ public class GpsLocationProvider extends LocationProviderImpl { * under most circumstances but may occassionally not report it * should return true. */ - @Override public boolean supportsBearing() { return true; } @@ -337,7 +468,6 @@ public class GpsLocationProvider extends LocationProviderImpl { * @return the power requirement for this provider, as one of the * constants Criteria.POWER_REQUIREMENT_*. */ - @Override public int getPowerRequirement() { return Criteria.POWER_HIGH; } @@ -348,17 +478,15 @@ public class GpsLocationProvider extends LocationProviderImpl { * @return the accuracy of location from this provider, as one * of the constants Criteria.ACCURACY_*. */ - @Override public int getAccuracy() { return Criteria.ACCURACY_FINE; } /** * Enables this provider. When enabled, calls to getStatus() - * and getLocation() must be handled. Hardware may be started up + * must be handled. Hardware may be started up * when the provider is enabled. */ - @Override public synchronized void enable() { if (Config.LOGD) Log.d(TAG, "enable"); if (mEnabled) return; @@ -385,10 +513,9 @@ public class GpsLocationProvider extends LocationProviderImpl { /** * Disables this provider. When disabled, calls to getStatus() - * and getLocation() need not be handled. Hardware may be shut + * need not be handled. Hardware may be shut * down while the provider is disabled. */ - @Override public synchronized void disable() { if (Config.LOGD) Log.d(TAG, "disable"); if (!mEnabled) return; @@ -412,15 +539,19 @@ public class GpsLocationProvider extends LocationProviderImpl { mNetworkThread = null; } + // The GpsEventThread does not wait for the GPS to shutdown + // so we need to report the GPS_STATUS_ENGINE_OFF event here + if (mNavigating) { + reportStatus(GPS_STATUS_ENGINE_OFF); + } + native_cleanup(); } - @Override public boolean isEnabled() { return mEnabled; } - @Override public int getStatus(Bundle extras) { if (extras != null) { extras.putInt("satellites", mSvCount); @@ -437,49 +568,23 @@ public class GpsLocationProvider extends LocationProviderImpl { } } - @Override public long getStatusUpdateTime() { return mStatusUpdateTime; } - @Override - public boolean getLocation(Location l) { - synchronized (mLocation) { - // don't report locations without latitude and longitude - if ((mLocationFlags & LOCATION_HAS_LAT_LONG) == 0) { - return false; - } - l.set(mLocation); - l.setExtras(mLocationExtras); - return true; - } - } - - @Override public void enableLocationTracking(boolean enable) { - if (mLocationTracking == enable) { - return; - } - if (enable) { - mFixRequestTime = System.currentTimeMillis(); mTTFF = 0; mLastFixTime = 0; startNavigating(); } else { + mAlarmManager.cancel(mWakeupIntent); + mAlarmManager.cancel(mTimeoutIntent); stopNavigating(); } - mLocationTracking = enable; - } - - @Override - public boolean isLocationTracking() { - return mLocationTracking; } - @Override public void setMinTime(long minTime) { - super.setMinTime(minTime); if (Config.LOGD) Log.d(TAG, "setMinTime " + minTime); if (minTime >= 0) { @@ -488,7 +593,6 @@ public class GpsLocationProvider extends LocationProviderImpl { interval = 1; } mFixInterval = interval; - native_set_fix_frequency(mFixInterval); } } @@ -510,48 +614,28 @@ public class GpsLocationProvider extends LocationProviderImpl { } } - public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException { - if (listener == null) throw new NullPointerException("listener is null in addGpsStatusListener"); - - synchronized(mListeners) { - IBinder binder = listener.asBinder(); - int size = mListeners.size(); - for (int i = 0; i < size; i++) { - Listener test = mListeners.get(i); - if (binder.equals(test.mListener.asBinder())) { - // listener already added - return; - } + public void addListener(int uid) { + mClientUids.put(uid, 0); + if (mNavigating) { + try { + mBatteryStats.noteStartGps(uid); + } catch (RemoteException e) { + Log.w(TAG, "RemoteException in addListener"); } - - Listener l = new Listener(listener); - binder.linkToDeath(l, 0); - mListeners.add(l); } } - - public void removeGpsStatusListener(IGpsStatusListener listener) { - if (listener == null) throw new NullPointerException("listener is null in addGpsStatusListener"); - synchronized(mListeners) { - IBinder binder = listener.asBinder(); - Listener l = null; - int size = mListeners.size(); - for (int i = 0; i < size && l == null; i++) { - Listener test = mListeners.get(i); - if (binder.equals(test.mListener.asBinder())) { - l = test; - } - } - - if (l != null) { - mListeners.remove(l); - binder.unlinkToDeath(l, 0); + public void removeListener(int uid) { + mClientUids.delete(uid); + if (mNavigating) { + try { + mBatteryStats.noteStopGps(uid); + } catch (RemoteException e) { + Log.w(TAG, "RemoteException in removeListener"); } } } - @Override public boolean sendExtraCommand(String command, Bundle extras) { if ("delete_aiding_data".equals(command)) { @@ -594,20 +678,29 @@ public class GpsLocationProvider extends LocationProviderImpl { public void startNavigating() { if (!mStarted) { - if (Config.LOGV) Log.v(TAG, "startNavigating"); + if (DEBUG) Log.d(TAG, "startNavigating"); mStarted = true; if (!native_start(mPositionMode, false, mFixInterval)) { mStarted = false; Log.e(TAG, "native_start failed in startNavigating()"); + return; } // reset SV count to zero - updateStatus(TEMPORARILY_UNAVAILABLE, 0); + updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0); + mFixCount = 0; + mFixRequestTime = System.currentTimeMillis(); + // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT + // and our fix interval is not short + if (mFixInterval >= NO_FIX_TIMEOUT) { + mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, + SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT * 1000, mTimeoutIntent); + } } } public void stopNavigating() { - if (Config.LOGV) Log.v(TAG, "stopNavigating"); + if (DEBUG) Log.d(TAG, "stopNavigating"); if (mStarted) { mStarted = false; native_stop(); @@ -616,16 +709,27 @@ public class GpsLocationProvider extends LocationProviderImpl { mLocationFlags = LOCATION_INVALID; // reset SV count to zero - updateStatus(TEMPORARILY_UNAVAILABLE, 0); + updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0); } } + private void hibernate() { + // stop GPS until our next fix interval arrives + stopNavigating(); + mFixCount = 0; + mAlarmManager.cancel(mTimeoutIntent); + mAlarmManager.cancel(mWakeupIntent); + long now = SystemClock.elapsedRealtime(); + mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, + SystemClock.elapsedRealtime() + mFixInterval * 1000, mWakeupIntent); + } + /** * called from native code to update our position. */ private void reportLocation(int flags, double latitude, double longitude, double altitude, float speed, float bearing, float accuracy, long timestamp) { - if (Config.LOGV) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude + + if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude + " timestamp: " + timestamp); mLastFixTime = System.currentTimeMillis(); @@ -679,19 +783,25 @@ public class GpsLocationProvider extends LocationProviderImpl { mLocation.removeAccuracy(); } - // Send to collector - if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG - && mCollector != null) { - mCollector.updateLocation(mLocation); + try { + mLocationManager.reportLocation(mLocation); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException calling reportLocation"); } } - if (mStarted && mStatus != AVAILABLE) { + if (mStarted && mStatus != LocationProvider.AVAILABLE) { + mAlarmManager.cancel(mTimeoutIntent); // send an intent to notify that the GPS is receiving fixes. Intent intent = new Intent(GPS_FIX_CHANGE_ACTION); intent.putExtra(EXTRA_ENABLED, true); mContext.sendBroadcast(intent); - updateStatus(AVAILABLE, mSvCount); + updateStatus(LocationProvider.AVAILABLE, mSvCount); + } + + if (mFixCount++ >= MIN_FIX_COUNT && mFixInterval > 1) { + if (DEBUG) Log.d(TAG, "exceeded MIN_FIX_COUNT"); + hibernate(); } } @@ -699,12 +809,16 @@ public class GpsLocationProvider extends LocationProviderImpl { * called from native code to update our status */ private void reportStatus(int status) { - if (Config.LOGV) Log.v(TAG, "reportStatus status: " + status); + if (VERBOSE) Log.v(TAG, "reportStatus status: " + status); boolean wasNavigating = mNavigating; mNavigating = (status == GPS_STATUS_SESSION_BEGIN); if (wasNavigating != mNavigating) { + if (mNavigating) { + if (DEBUG) Log.d(TAG, "Acquiring wakelock"); + mWakeLock.acquire(); + } synchronized(mListeners) { int size = mListeners.size(); for (int i = 0; i < size; i++) { @@ -724,10 +838,29 @@ public class GpsLocationProvider extends LocationProviderImpl { } } + try { + // update battery stats + for (int i=mClientUids.size() - 1; i >= 0; i--) { + int uid = mClientUids.keyAt(i); + if (mNavigating) { + mBatteryStats.noteStartGps(uid); + } else { + mBatteryStats.noteStopGps(uid); + } + } + } catch (RemoteException e) { + Log.w(TAG, "RemoteException in reportStatus"); + } + // send an intent to notify that the GPS has been enabled or disabled. Intent intent = new Intent(GPS_ENABLED_CHANGE_ACTION); intent.putExtra(EXTRA_ENABLED, mNavigating); mContext.sendBroadcast(intent); + + if (!mNavigating) { + if (DEBUG) Log.d(TAG, "Releasing wakelock"); + mWakeLock.release(); + } } } @@ -755,12 +888,12 @@ public class GpsLocationProvider extends LocationProviderImpl { } } - if (Config.LOGD) { - if (Config.LOGV) Log.v(TAG, "SV count: " + svCount + + if (VERBOSE) { + Log.v(TAG, "SV count: " + svCount + " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) + " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK])); for (int i = 0; i < svCount; i++) { - if (Config.LOGV) Log.v(TAG, "sv: " + mSvs[i] + + Log.v(TAG, "sv: " + mSvs[i] + " snr: " + (float)mSnrs[i]/10 + " elev: " + mSvElevations[i] + " azimuth: " + mSvAzimuths[i] + @@ -772,16 +905,53 @@ public class GpsLocationProvider extends LocationProviderImpl { updateStatus(mStatus, svCount); - if (mNavigating && mStatus == AVAILABLE && mLastFixTime > 0 && - System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) { + if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 && + System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT * 1000) { // send an intent to notify that the GPS is no longer receiving fixes. Intent intent = new Intent(GPS_FIX_CHANGE_ACTION); intent.putExtra(EXTRA_ENABLED, false); mContext.sendBroadcast(intent); - updateStatus(TEMPORARILY_UNAVAILABLE, mSvCount); + updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount); } } - + + /** + * called from native code to update AGPS status + */ + private void reportAGpsStatus(int type, int status) { + switch (status) { + case GPS_REQUEST_AGPS_DATA_CONN: + int result = mConnMgr.startUsingNetworkFeature( + ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL); + if (result == Phone.APN_ALREADY_ACTIVE) { + native_agps_data_conn_open(mAGpsApn); + mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN; + } else if (result == Phone.APN_REQUEST_STARTED) { + mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING; + } else { + native_agps_data_conn_failed(); + } + break; + case GPS_RELEASE_AGPS_DATA_CONN: + if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) { + mConnMgr.stopUsingNetworkFeature( + ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL); + native_agps_data_conn_closed(); + mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED; + } + break; + case GPS_AGPS_DATA_CONNECTED: + // Log.d(TAG, "GPS_AGPS_DATA_CONNECTED"); + break; + case GPS_AGPS_DATA_CONN_DONE: + // Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE"); + break; + case GPS_AGPS_DATA_CONN_FAILED: + // Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED"); + break; + } + } + private void xtraDownloadRequest() { if (Config.LOGD) Log.d(TAG, "xtraDownloadRequest"); if (mNetworkThread != null) { @@ -789,6 +959,29 @@ public class GpsLocationProvider extends LocationProviderImpl { } } + private boolean setAGpsServer(int type, String host, int port) { + try { + InetAddress inetAddress = InetAddress.getByName(host); + if (inetAddress != null) { + byte[] addrBytes = inetAddress.getAddress(); + long addr = 0; + for (int i = 0; i < addrBytes.length; i++) { + int temp = addrBytes[i]; + // signed -> unsigned + if (temp < 0) temp = 256 + temp; + addr = addr * 256 + temp; + } + // use MS-Based position mode if SUPL support is enabled + mPositionMode = GPS_POSITION_MODE_MS_BASED; + native_set_agps_server(type, (int)addr, port); + } + } catch (UnknownHostException e) { + Log.e(TAG, "unknown host for server " + host); + return false; + } + return true; + } + private class GpsEventThread extends Thread { public GpsEventThread() { @@ -797,8 +990,8 @@ public class GpsLocationProvider extends LocationProviderImpl { public void run() { if (Config.LOGD) Log.d(TAG, "GpsEventThread starting"); - // thread exits after disable() is called and navigation has stopped - while (mEnabled || mNavigating) { + // Exit as soon as disable() is called instead of waiting for the GPS to stop. + while (mEnabled) { // this will wait for an event from the GPS, // which will be reported via reportLocation or reportStatus native_wait_for_event(); @@ -860,7 +1053,8 @@ public class GpsLocationProvider extends LocationProviderImpl { } } waitTime = getWaitTime(); - } while (!mDone && ((!mXtraDownloadRequested && !mSetSuplServer && waitTime > 0) + } while (!mDone && ((!mXtraDownloadRequested && + !mSetSuplServer && !mSetC2KServer && waitTime > 0) || !mNetworkAvailable)); if (Config.LOGD) Log.d(TAG, "NetworkThread out of wake loop"); @@ -887,26 +1081,15 @@ public class GpsLocationProvider extends LocationProviderImpl { } } - // Set the SUPL server address if we have not yet + // Set the AGPS server addresses if we have not yet if (mSetSuplServer) { - try { - InetAddress inetAddress = InetAddress.getByName(mSuplHost); - if (inetAddress != null) { - byte[] addrBytes = inetAddress.getAddress(); - long addr = 0; - for (int i = 0; i < addrBytes.length; i++) { - int temp = addrBytes[i]; - // signed -> unsigned - if (temp < 0) temp = 256 + temp; - addr = addr * 256 + temp; - } - // use MS-Based position mode if SUPL support is enabled - mPositionMode = GPS_POSITION_MODE_MS_BASED; - native_set_supl_server((int)addr, mSuplPort); - mSetSuplServer = false; - } - } catch (UnknownHostException e) { - Log.e(TAG, "unknown host for SUPL server " + mSuplHost); + if (setAGpsServer(AGPS_TYPE_SUPL, mSuplHost, mSuplPort)) { + mSetSuplServer = false; + } + } + if (mSetC2KServer) { + if (setAGpsServer(AGPS_TYPE_C2K, mC2KHost, mC2KPort)) { + mSetC2KServer = false; } } @@ -1000,7 +1183,9 @@ public class GpsLocationProvider extends LocationProviderImpl { private native boolean native_supports_xtra(); private native void native_inject_xtra_data(byte[] data, int length); - // SUPL Support - private native void native_set_supl_server(int addr, int port); - private native void native_set_supl_apn(String apn); + // AGPS Support + private native void native_agps_data_conn_open(String apn); + private native void native_agps_data_conn_closed(); + private native void native_agps_data_conn_failed(); + private native void native_set_agps_server(int type, int addr, int port); } diff --git a/location/java/com/android/internal/location/GpsXtraDownloader.java b/location/java/com/android/internal/location/GpsXtraDownloader.java index b8545a6..2a8be57 100644 --- a/location/java/com/android/internal/location/GpsXtraDownloader.java +++ b/location/java/com/android/internal/location/GpsXtraDownloader.java @@ -70,11 +70,11 @@ public class GpsXtraDownloader { if (server1 != null) mXtraServers[count++] = server1; if (server2 != null) mXtraServers[count++] = server2; if (server3 != null) mXtraServers[count++] = server3; - } - - // randomize first server - Random random = new Random(); - mNextServerIndex = random.nextInt(count); + + // randomize first server + Random random = new Random(); + mNextServerIndex = random.nextInt(count); + } } byte[] downloadXtraData() { diff --git a/location/java/com/android/internal/location/ILocationCollector.java b/location/java/com/android/internal/location/ILocationCollector.java deleted file mode 100644 index 8a7cdcc..0000000 --- a/location/java/com/android/internal/location/ILocationCollector.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.location; - -import android.location.Location; -import android.net.wifi.ScanResult; - -import com.android.internal.location.CellState; - -import java.util.List; - -/** - * Listens for GPS and cell/wifi changes and anonymously uploads to server for - * improving quality of service of NetworkLocationProvider. This service is only enabled when - * the user has enabled the network location provider. - * - * {@hide} - */ -public interface ILocationCollector { - /** - * Updates GPS location if collection is enabled - * - * @param location location object - */ - abstract public void updateLocation(Location location); - - /** - * Updates wifi scan results if collection is enabled - * - * @param currentScanResults scan results - */ - abstract public void updateWifiScanResults(List currentScanResults); - - /** - * Updates the status of the network location provider. - * - * @param enabled true if user has enabled network location based on Google's database - * of wifi points and cell towers. - */ - abstract public void updateNetworkProviderStatus(boolean enabled); - - /** - * Updates cell tower state. This is usually always up to date so should be uploaded - * each time a new location is available. - * - * @param newState cell state - */ - abstract public void updateCellState(CellState newState); - - /** - * Updates the battery health. Battery level is healthy if there is greater than - * {@link #MIN_BATTERY_LEVEL} percentage left or if the device is plugged in - * - * @param scale maximum scale for battery - * @param level current level - * @param plugged true if device is plugged in - */ - abstract public void updateBatteryState(int scale, int level, boolean plugged); -} diff --git a/location/java/com/android/internal/location/INetworkLocationManager.java b/location/java/com/android/internal/location/INetworkLocationManager.java deleted file mode 100644 index d85ff0a..0000000 --- a/location/java/com/android/internal/location/INetworkLocationManager.java +++ /dev/null @@ -1,37 +0,0 @@ - /* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.location; - -import android.content.Context; - -/** - * Used to register network location and collection services - * with the Location Manager Service. - * - * {@hide} - */ -public interface INetworkLocationManager { - - /* callback to allow installation to occur in Location Manager's thread */ - public interface InstallCallback { - void installNetworkLocationProvider(INetworkLocationManager manager); - } - - void setInstallCallback(InstallCallback callback); - void setNetworkLocationProvider(INetworkLocationProvider provider); - void setLocationCollector(ILocationCollector collector); -} \ No newline at end of file diff --git a/location/java/com/android/internal/location/INetworkLocationProvider.java b/location/java/com/android/internal/location/INetworkLocationProvider.java deleted file mode 100644 index 730cb48..0000000 --- a/location/java/com/android/internal/location/INetworkLocationProvider.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.location; - -import android.location.Address; -import android.location.Location; -import android.net.wifi.ScanResult; - -import com.google.common.io.protocol.ProtoBuf; - -import java.io.IOException; -import java.util.Collection; -import java.util.List; -import java.util.Locale; - -/** - * Interface for network location provider - * - * {@hide} - */ -public interface INetworkLocationProvider { - - public interface Callback { - - /** - * Callback function to notify of a received network location - * - * @param location location object that is received. may be null if not a valid location - * @param successful true if network query was successful, even if no location was found - */ - void locationReceived(Location location, boolean successful); - } - - /** - * Updates the current cell lock status. - * - * @param acquired true if a cell lock has been acquired - */ - abstract public void updateCellLockStatus(boolean acquired); - - /** - * Notifies the provider if Wifi has been enabled or disabled - * by the user - * - * @param enabled true if wifi is enabled; false otherwise - */ - abstract public void updateWifiEnabledState(boolean enabled); - - /** - * Notifies the provider that there are scan results available. - * - * @param scanResults list of wifi scan results - */ - abstract public void updateWifiScanResults(List scanResults); - - /** - * Adds a list of application clients - * Only used by the NetworkLocationProvider - * - * @param applications list of package names - */ - abstract public void addListener(String[] applications); - - /** - * Removes a list of application clients - * Only used by the NetworkLocationProvider - * - * @param applications list of package names - */ - abstract public void removeListener(String[] applications); - - - abstract public String getFromLocation(double latitude, double longitude, int maxResults, - String language, String country, String variant, String appName, List

addrs); - - abstract public String getFromLocationName(String locationName, - double lowerLeftLatitude, double lowerLeftLongitude, - double upperRightLatitude, double upperRightLongitude, int maxResults, - String language, String country, String variant, String appName, List
addrs); - -} diff --git a/location/java/com/android/internal/location/LocationProviderProxy.java b/location/java/com/android/internal/location/LocationProviderProxy.java new file mode 100644 index 0000000..b40cdca --- /dev/null +++ b/location/java/com/android/internal/location/LocationProviderProxy.java @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.location; + +import android.location.Address; +import android.location.ILocationProvider; +import android.location.Location; +import android.location.LocationManager; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import java.util.List; + +/** + * A class for proxying remote ILocationProvider implementations. + * + * {@hide} + */ +public class LocationProviderProxy implements IBinder.DeathRecipient { + + private static final String TAG = "LocationProviderProxy"; + + private final String mName; + private final ILocationProvider mProvider; + private boolean mLocationTracking = false; + private long mMinTime = 0; + private boolean mDead; + + public LocationProviderProxy(String name, ILocationProvider provider) { + mName = name; + mProvider = provider; + try { + provider.asBinder().linkToDeath(this, 0); + } catch (RemoteException e) { + Log.e(TAG, "linkToDeath failed", e); + mDead = true; + } + } + + public String getName() { + return mName; + } + + public boolean isDead() { + return mDead; + } + + public boolean requiresNetwork() { + try { + return mProvider.requiresNetwork(); + } catch (RemoteException e) { + Log.e(TAG, "requiresNetwork failed", e); + return false; + } + } + + public boolean requiresSatellite() { + try { + return mProvider.requiresSatellite(); + } catch (RemoteException e) { + Log.e(TAG, "requiresSatellite failed", e); + return false; + } + } + + public boolean requiresCell() { + try { + return mProvider.requiresCell(); + } catch (RemoteException e) { + Log.e(TAG, "requiresCell failed", e); + return false; + } + } + + public boolean hasMonetaryCost() { + try { + return mProvider.hasMonetaryCost(); + } catch (RemoteException e) { + Log.e(TAG, "hasMonetaryCost failed", e); + return false; + } + } + + public boolean supportsAltitude() { + try { + return mProvider.supportsAltitude(); + } catch (RemoteException e) { + Log.e(TAG, "supportsAltitude failed", e); + return false; + } + } + + public boolean supportsSpeed() { + try { + return mProvider.supportsSpeed(); + } catch (RemoteException e) { + Log.e(TAG, "supportsSpeed failed", e); + return false; + } + } + + public boolean supportsBearing() { + try { + return mProvider.supportsBearing(); + } catch (RemoteException e) { + Log.e(TAG, "supportsBearing failed", e); + return false; + } + } + + public int getPowerRequirement() { + try { + return mProvider.getPowerRequirement(); + } catch (RemoteException e) { + Log.e(TAG, "getPowerRequirement failed", e); + return 0; + } + } + + public int getAccuracy() { + try { + return mProvider.getAccuracy(); + } catch (RemoteException e) { + Log.e(TAG, "getAccuracy failed", e); + return 0; + } + } + + public void enable() { + try { + mProvider.enable(); + } catch (RemoteException e) { + Log.e(TAG, "enable failed", e); + } + } + + public void disable() { + try { + mProvider.disable(); + } catch (RemoteException e) { + Log.e(TAG, "disable failed", e); + } + } + + public boolean isEnabled() { + try { + return mProvider.isEnabled(); + } catch (RemoteException e) { + Log.e(TAG, "isEnabled failed", e); + return false; + } + } + + public int getStatus(Bundle extras) { + try { + return mProvider.getStatus(extras); + } catch (RemoteException e) { + Log.e(TAG, "getStatus failed", e); + return 0; + } + } + + public long getStatusUpdateTime() { + try { + return mProvider.getStatusUpdateTime(); + } catch (RemoteException e) { + Log.e(TAG, "getStatusUpdateTime failed", e); + return 0; + } + } + + public boolean isLocationTracking() { + return mLocationTracking; + } + + public void enableLocationTracking(boolean enable) { + mLocationTracking = enable; + try { + mProvider.enableLocationTracking(enable); + } catch (RemoteException e) { + Log.e(TAG, "enableLocationTracking failed", e); + } + } + + public long getMinTime() { + return mMinTime; + } + + public void setMinTime(long minTime) { + mMinTime = minTime; + try { + mProvider.setMinTime(minTime); + } catch (RemoteException e) { + Log.e(TAG, "setMinTime failed", e); + } + } + + public void updateNetworkState(int state) { + try { + mProvider.updateNetworkState(state); + } catch (RemoteException e) { + Log.e(TAG, "updateNetworkState failed", e); + } + } + + public boolean sendExtraCommand(String command, Bundle extras) { + try { + return mProvider.sendExtraCommand(command, extras); + } catch (RemoteException e) { + Log.e(TAG, "sendExtraCommand failed", e); + return false; + } + } + + public void addListener(int uid) { + try { + mProvider.addListener(uid); + } catch (RemoteException e) { + Log.e(TAG, "addListener failed", e); + } + } + + public void removeListener(int uid) { + try { + mProvider.removeListener(uid); + } catch (RemoteException e) { + Log.e(TAG, "removeListener failed", e); + } + } + + public void binderDied() { + Log.w(TAG, "Location Provider " + mName + " died"); + mDead = true; + } +} diff --git a/location/java/com/android/internal/location/MockProvider.java b/location/java/com/android/internal/location/MockProvider.java new file mode 100644 index 0000000..f167a44 --- /dev/null +++ b/location/java/com/android/internal/location/MockProvider.java @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.location; + +import android.location.ILocationManager; +import android.location.ILocationProvider; +import android.location.Location; +import android.location.LocationProvider; +import android.os.Bundle; +import android.os.RemoteException; +import android.util.Log; +import android.util.PrintWriterPrinter; + +import java.io.PrintWriter; + +/** + * A mock location provider used by LocationManagerService to implement test providers. + * + * {@hide} + */ +public class MockProvider extends ILocationProvider.Stub { + private final String mName; + private final ILocationManager mLocationManager; + private final boolean mRequiresNetwork; + private final boolean mRequiresSatellite; + private final boolean mRequiresCell; + private final boolean mHasMonetaryCost; + private final boolean mSupportsAltitude; + private final boolean mSupportsSpeed; + private final boolean mSupportsBearing; + private final int mPowerRequirement; + private final int mAccuracy; + private final Location mLocation; + private int mStatus; + private long mStatusUpdateTime; + private final Bundle mExtras = new Bundle(); + private boolean mHasLocation; + private boolean mHasStatus; + private boolean mEnabled; + + private static final String TAG = "MockProvider"; + + public MockProvider(String name, ILocationManager locationManager, + boolean requiresNetwork, boolean requiresSatellite, + boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude, + boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) { + mName = name; + mLocationManager = locationManager; + mRequiresNetwork = requiresNetwork; + mRequiresSatellite = requiresSatellite; + mRequiresCell = requiresCell; + mHasMonetaryCost = hasMonetaryCost; + mSupportsAltitude = supportsAltitude; + mSupportsBearing = supportsBearing; + mSupportsSpeed = supportsSpeed; + mPowerRequirement = powerRequirement; + mAccuracy = accuracy; + mLocation = new Location(name); + } + + public void disable() { + mEnabled = false; + } + + public void enable() { + mEnabled = true; + } + + public int getStatus(Bundle extras) { + if (mHasStatus) { + extras.clear(); + extras.putAll(mExtras); + return mStatus; + } else { + return LocationProvider.AVAILABLE; + } + } + + public long getStatusUpdateTime() { + return mStatusUpdateTime; + } + + public boolean isEnabled() { + return mEnabled; + } + + public int getAccuracy() { + return mAccuracy; + } + + public int getPowerRequirement() { + return mPowerRequirement; + } + + public boolean hasMonetaryCost() { + return mHasMonetaryCost; + } + + public boolean requiresCell() { + return mRequiresCell; + } + + public boolean requiresNetwork() { + return mRequiresNetwork; + } + + public boolean requiresSatellite() { + return mRequiresSatellite; + } + + public boolean supportsAltitude() { + return mSupportsAltitude; + } + + public boolean supportsBearing() { + return mSupportsBearing; + } + + public boolean supportsSpeed() { + return mSupportsSpeed; + } + + public void setLocation(Location l) { + mLocation.set(l); + mHasLocation = true; + try { + mLocationManager.reportLocation(mLocation); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException calling reportLocation"); + } + } + + public void clearLocation() { + mHasLocation = false; + } + + public void setStatus(int status, Bundle extras, long updateTime) { + mStatus = status; + mStatusUpdateTime = updateTime; + mExtras.clear(); + if (extras != null) { + mExtras.putAll(extras); + } + mHasStatus = true; + } + + public void clearStatus() { + mHasStatus = false; + mStatusUpdateTime = 0; + } + + public void enableLocationTracking(boolean enable) { + } + + public void setMinTime(long minTime) { + } + + public void updateNetworkState(int state) { + } + + public boolean sendExtraCommand(String command, Bundle extras) { + return false; + } + + public void addListener(int uid) { + } + + public void removeListener(int uid) { + } + + public void dump(PrintWriter pw, String prefix) { + pw.println(prefix + mName); + pw.println(prefix + "mHasLocation=" + mHasLocation); + pw.println(prefix + "mLocation:"); + mLocation.dump(new PrintWriterPrinter(pw), prefix + " "); + pw.println(prefix + "mHasStatus=" + mHasStatus); + pw.println(prefix + "mStatus=" + mStatus); + pw.println(prefix + "mStatusUpdateTime=" + mStatusUpdateTime); + pw.println(prefix + "mExtras=" + mExtras); + } +} diff --git a/location/java/com/android/internal/location/TrackProvider.java b/location/java/com/android/internal/location/TrackProvider.java deleted file mode 100644 index 545d7dc..0000000 --- a/location/java/com/android/internal/location/TrackProvider.java +++ /dev/null @@ -1,720 +0,0 @@ -// Copyright 2007 The Android Open Source Project - -package com.android.internal.location; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlPullParserFactory; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.Reader; -import java.util.ArrayList; -import java.util.List; -import java.util.StringTokenizer; - -import android.location.Criteria; -import android.location.Location; -import android.location.LocationProviderImpl; -import android.os.Bundle; -import android.util.Config; -import android.util.Log; - -/** - * A dummy provider that returns positions interpolated from a sequence - * of caller-supplied waypoints. The waypoints are supplied as a - * String containing one or more numeric quadruples of the form: - *
- * - * - * - *

The waypoints must be supplied in increasing timestamp order. - * - *

The time at which the provider is constructed is considered to - * be time 0, and further requests for positions will return a - * position that is linearly interpolated between the waypoints whose - * timestamps are closest to the amount of wall clock time that has - * elapsed since time 0. - * - *

Following the time of the last waypoint, the position of that - * waypoint will continue to be returned indefinitely. - * - * {@hide} - */ -public class TrackProvider extends LocationProviderImpl { - static final String LOG_TAG = "TrackProvider"; - - private static final long INTERVAL = 1000L; - - private boolean mEnabled = true; - - private double mLatitude; - private double mLongitude; - private boolean mHasAltitude; - private boolean mHasBearing; - private boolean mHasSpeed; - private double mAltitude; - private float mBearing; - private float mSpeed; - private Bundle mExtras; - - private long mBaseTime; - private long mLastTime = -1L; - private long mTime; - - private long mMinTime; - private long mMaxTime; - - private List mWaypoints = new ArrayList(); - private int mWaypointIndex = 0; - - private boolean mRequiresNetwork = false; - private boolean mRequiresSatellite = false; - private boolean mRequiresCell = false; - private boolean mHasMonetaryCost = false; - private boolean mSupportsAltitude = true; - private boolean mSupportsSpeed = true; - private boolean mSupportsBearing = true; - private boolean mRepeat = false; - private int mPowerRequirement = Criteria.POWER_LOW; - private int mAccuracy = Criteria.ACCURACY_COARSE; - - private float mTrackSpeed = 100.0f; // km/hr - default for kml tracks - - private Location mInitialLocation; - - private void close(Reader rdr) { - try { - if (rdr != null) { - rdr.close(); - } - } catch (IOException e) { - Log.w(LOG_TAG, "Exception closing reader", e); - } - } - - public void readTrack(File trackFile) { - BufferedReader br = null; - try { - br = new BufferedReader(new FileReader(trackFile), 8192); - String s; - - long lastTime = -Long.MAX_VALUE; - while ((s = br.readLine()) != null) { - String[] tokens = s.split("\\s+"); - if (tokens.length != 4 && tokens.length != 6) { - Log.e(LOG_TAG, "Got track \"" + s + - "\", wanted