summaryrefslogtreecommitdiffstats
path: root/location/java
diff options
context:
space:
mode:
authorJean-Baptiste Queru <jbq@google.com>2009-05-20 11:28:04 -0700
committerJean-Baptiste Queru <jbq@google.com>2009-05-20 11:28:04 -0700
commit843ef36f7b96cc19ea7d2996b7c8661b41ec3452 (patch)
tree560e1648c99a93986f8b7deef851ef8bb8029db7 /location/java
parent358d23017d0d6c4636eb7599ae7a9b48108899a3 (diff)
downloadframeworks_base-843ef36f7b96cc19ea7d2996b7c8661b41ec3452.zip
frameworks_base-843ef36f7b96cc19ea7d2996b7c8661b41ec3452.tar.gz
frameworks_base-843ef36f7b96cc19ea7d2996b7c8661b41ec3452.tar.bz2
donut snapshot
Diffstat (limited to 'location/java')
-rw-r--r--location/java/android/location/Geocoder.java16
-rw-r--r--location/java/android/location/GpsStatus.java2
-rw-r--r--location/java/android/location/IGeocodeProvider.aidl35
-rw-r--r--location/java/android/location/IGpsStatusProvider.aidl29
-rw-r--r--location/java/android/location/ILocationCollector.aidl (renamed from location/java/com/android/internal/location/INetworkLocationManager.java)31
-rw-r--r--location/java/android/location/ILocationManager.aidl18
-rw-r--r--location/java/android/location/ILocationProvider.aidl47
-rw-r--r--location/java/android/location/LocationManager.java105
-rw-r--r--location/java/android/location/LocationProvider.java4
-rw-r--r--location/java/android/location/LocationProviderImpl.java261
-rw-r--r--location/java/com/android/internal/location/CellState.java292
-rw-r--r--location/java/com/android/internal/location/DummyLocationProvider.java (renamed from location/java/android/location/DummyLocationProvider.java)8
-rw-r--r--location/java/com/android/internal/location/GpsLocationProvider.java489
-rw-r--r--location/java/com/android/internal/location/GpsXtraDownloader.java10
-rw-r--r--location/java/com/android/internal/location/ILocationCollector.java73
-rw-r--r--location/java/com/android/internal/location/INetworkLocationProvider.java95
-rw-r--r--location/java/com/android/internal/location/LocationProviderProxy.java251
-rw-r--r--location/java/com/android/internal/location/MockProvider.java195
-rw-r--r--location/java/com/android/internal/location/TrackProvider.java720
19 files changed, 1037 insertions, 1644 deletions
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<Address> 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<Address> 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/com/android/internal/location/INetworkLocationManager.java b/location/java/android/location/ILocationCollector.aidl
index d85ff0a..b2e1796 100644
--- a/location/java/com/android/internal/location/INetworkLocationManager.java
+++ b/location/java/android/location/ILocationCollector.aidl
@@ -1,4 +1,4 @@
- /*
+/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,24 +14,23 @@
* limitations under the License.
*/
-package com.android.internal.location;
+package android.location;
-import android.content.Context;
+import android.location.Location;
/**
- * Used to register network location and collection services
- * with the Location Manager Service.
+ * 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 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
+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<Address> 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<LocationProviderImpl> sProviders =
- new ArrayList<LocationProviderImpl>();
- private static HashMap<String, LocationProviderImpl> sProvidersByName
- = new HashMap<String, LocationProviderImpl>();
-
- 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<LocationProviderImpl> getProviders() {
- return new ArrayList<LocationProviderImpl>(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.
- *
- * <p> 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<NeighborCell> 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<NeighborCell>();
- List<NeighboringCellInfo> 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<NeighborCell> 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/android/location/DummyLocationProvider.java b/location/java/com/android/internal/location/DummyLocationProvider.java
index e1cd4e9..ff5e27b 100644
--- a/location/java/android/location/DummyLocationProvider.java
+++ b/location/java/com/android/internal/location/DummyLocationProvider.java
@@ -14,7 +14,9 @@
* limitations under the License.
*/
-package android.location;
+package com.android.internal.location;
+
+import android.location.LocationProvider;
/**
* A stub implementation of LocationProvider used by LocationManager.
@@ -24,7 +26,7 @@ package android.location;
*
* {@hide}
*/
-class DummyLocationProvider extends LocationProvider {
+public class DummyLocationProvider extends LocationProvider {
private static final String TAG = "DummyLocationProvider";
@@ -39,7 +41,7 @@ class DummyLocationProvider extends LocationProvider {
int mPowerRequirement;
int mAccuracy;
- /* package */ DummyLocationProvider(String name) {
+ public DummyLocationProvider(String name) {
super(name);
}
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<Listener> mListeners = new ArrayList<Listener>();
@@ -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<ScanResult> 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/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<ScanResult> 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<Address> 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<Address> 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:
- * <br>
- * <code>
- * <time in millis> <latitude> <longitude> <altitude>
- * </code>
- *
- * <p> The waypoints must be supplied in increasing timestamp order.
- *
- * <p> 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.
- *
- * <p> 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<Waypoint> mWaypoints = new ArrayList<Waypoint>();
- 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 <time> <long> <lat> <alt> [<bearing> <speed>]");
- continue;
- }
- long time;
- double longitude, latitude, altitude;
- try {
- time = Long.parseLong(tokens[0]);
- longitude = Double.parseDouble(tokens[1]);
- latitude = Double.parseDouble(tokens[2]);
- altitude = Double.parseDouble(tokens[3]);
- } catch (NumberFormatException e) {
- Log.e(LOG_TAG, "Got track \"" + s +
- "\", wanted <time> <long> <lat> <alt> " +
- "[<bearing> <speed>]", e);
- continue;
- }
-
- Waypoint w = new Waypoint(getName(), time, latitude, longitude, altitude);
- if (tokens.length >= 6) {
- float bearing, speed;
- try {
- bearing = Float.parseFloat(tokens[4]);
- speed = Float.parseFloat(tokens[5]);
- w.setBearing(bearing);
- w.setSpeed(speed);
- } catch (NumberFormatException e) {
- Log.e(LOG_TAG, "Ignoring bearing and speed \"" +
- tokens[4] + "\", \"" + tokens[5] + "\"", e);
- }
- }
-
- if (mInitialLocation == null) {
- mInitialLocation = w.getLocation();
- }
-
- // Ignore waypoints whose time is less than or equal to 0 or
- // the time of the previous waypoint
- if (time < 0) {
- Log.e(LOG_TAG, "Ignoring waypoint at negative time=" + time);
- continue;
- }
- if (time <= lastTime) {
- Log.e(LOG_TAG, "Ignoring waypoint at time=" + time +
- " (< " + lastTime + ")");
- continue;
- }
-
- mWaypoints.add(w);
- lastTime = time;
- }
-
- setTimes();
- return;
- } catch (IOException e) {
- Log.e(LOG_TAG, "Exception reading track file", e);
- mWaypoints.clear();
- } finally {
- close(br);
- }
- }
-
- public void readKml(File kmlFile) {
- FileReader kmlReader = null;
- try {
- kmlReader = new FileReader(kmlFile);
- XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
- XmlPullParser xpp = factory.newPullParser();
- xpp.setInput(kmlReader);
-
- // Concatenate the text of each <coordinates> tag
- boolean inCoordinates = false;
- StringBuilder sb = new StringBuilder();
- int eventType = xpp.getEventType();
- do {
- if (eventType == XmlPullParser.START_DOCUMENT) {
- // do nothing
- } else if (eventType == XmlPullParser.END_DOCUMENT) {
- // do nothing
- } else if (eventType == XmlPullParser.START_TAG) {
- String startTagName = xpp.getName();
- if (startTagName.equals("coordinates")) {
- inCoordinates = true;
- }
- } else if (eventType == XmlPullParser.END_TAG) {
- String endTagName = xpp.getName();
- if (endTagName.equals("coordinates")) {
- inCoordinates = false;
- }
- } else if (eventType == XmlPullParser.TEXT) {
- if (inCoordinates) {
- sb.append(xpp.getText());
- sb.append(' ');
- }
- }
- eventType = xpp.next();
- } while (eventType != XmlPullParser.END_DOCUMENT);
-
- String coordinates = sb.toString();
-
- // Parse the "lon,lat,alt" triples and supply times
- // for each waypoint based on a constant speed
- Location loc = null;
- double KM_PER_HOUR = mTrackSpeed;
- double KM_PER_METER = 1.0 / 1000.0;
- double MILLIS_PER_HOUR = 60.0 * 60.0 * 1000.0;
- double MILLIS_PER_METER =
- (1.0 / KM_PER_HOUR) * (KM_PER_METER) * (MILLIS_PER_HOUR);
- long time = 0L;
-
- StringTokenizer st = new StringTokenizer(coordinates, ", ");
- while (st.hasMoreTokens()) {
- try {
- String lon = st.nextToken();
- String lat = st.nextToken();
- String alt = st.nextToken();
- if (Config.LOGD) {
- Log.d(LOG_TAG,
- "lon=" + lon + ", lat=" + lat + ", alt=" + alt);
- }
-
- double nLongitude = Double.parseDouble(lon);
- double nLatitude = Double.parseDouble(lat);
- double nAltitude = Double.parseDouble(alt);
-
- Location nLoc = new Location(getName());
- nLoc.setLatitude(nLatitude);
- nLoc.setLongitude(nLongitude);
- if (loc != null) {
- double distance = loc.distanceTo(nLoc);
- if (Config.LOGD) {
- Log.d(LOG_TAG, "distance = " + distance);
- }
- time += (long) (distance * MILLIS_PER_METER);
- }
-
- Waypoint w = new Waypoint(getName(), time,
- nLatitude, nLongitude, nAltitude);
- if (supportsSpeed()) {
- w.setSpeed(mTrackSpeed);
- }
- if (supportsBearing()) {
- w.setBearing(0.0f);
- }
- mWaypoints.add(w);
-
- if (mInitialLocation == null) {
- mInitialLocation = w.getLocation();
- }
-
- loc = nLoc;
- } catch (NumberFormatException nfe) {
- Log.e(LOG_TAG, "Got NumberFormatException reading KML data: " +
- nfe, nfe);
- }
- }
-
- setTimes();
- return;
- } catch (IOException ioe) {
- mWaypoints.clear();
- Log.e(LOG_TAG, "Exception reading KML data: " + ioe, ioe);
- // fall through
- } catch (XmlPullParserException xppe) {
- mWaypoints.clear();
- Log.e(LOG_TAG, "Exception reading KML data: " + xppe, xppe);
- // fall through
- } finally {
- close(kmlReader);
- }
- }
-
- public void readNmea(String name, File file) {
- BufferedReader br = null;
- try {
- br = new BufferedReader(new FileReader(file), 8192);
- String s;
-
- String provider = getName();
- NmeaParser parser = new NmeaParser(name);
- while ((s = br.readLine()) != null) {
- boolean newWaypoint = parser.parseSentence(s);
- if (newWaypoint) {
- Location loc = parser.getLocation();
- Waypoint w = new Waypoint(loc);
- mWaypoints.add(w);
- // Log.i(TAG, "Got waypoint " + w);
- }
- }
-
- setTimes();
- return;
- } catch (IOException ioe) {
- Log.e(LOG_TAG, "Exception reading NMEA data: " + ioe);
- mWaypoints.clear();
- } finally {
- close(br);
- }
- }
-
- private static boolean booleanVal(String tf) {
- return (tf == null) || (tf.equalsIgnoreCase("true"));
- }
-
- private static int intVal(String val) {
- try {
- return (val == null) ? 0 : Integer.parseInt(val);
- } catch (NumberFormatException nfe) {
- return 0;
- }
- }
-
- private static float floatVal(String val) {
- try {
- return (val == null) ? 0 : Float.parseFloat(val);
- } catch (NumberFormatException nfe) {
- return 0.0f;
- }
- }
-
- public void readProperties(File propertiesFile) {
- BufferedReader br = null;
- if (!propertiesFile.exists()) {
- return;
- }
- try {
- if (Config.LOGD) {
- Log.d(LOG_TAG, "Loading properties file " +
- propertiesFile.getPath());
- }
- br = new BufferedReader(new FileReader(propertiesFile), 8192);
-
- String s;
- while ((s = br.readLine()) != null) {
- StringTokenizer st = new StringTokenizer(s);
- String command = null;
- String value = null;
- if (!st.hasMoreTokens()) {
- continue;
- }
- command = st.nextToken();
- if (st.hasMoreTokens()) {
- value = st.nextToken();
- }
-
- if (command.equalsIgnoreCase("requiresNetwork")) {
- setRequiresNetwork(booleanVal(value));
- } else if (command.equalsIgnoreCase("requiresSatellite")) {
- setRequiresSatellite(booleanVal(value));
- } else if (command.equalsIgnoreCase("requiresCell")) {
- setRequiresCell(booleanVal(value));
- } else if (command.equalsIgnoreCase("hasMonetaryCost")) {
- setHasMonetaryCost(booleanVal(value));
- } else if (command.equalsIgnoreCase("supportsAltitude")) {
- setSupportsAltitude(booleanVal(value));
- } else if (command.equalsIgnoreCase("supportsBearing")) {
- setSupportsBearing(booleanVal(value));
- } else if (command.equalsIgnoreCase("repeat")) {
- setRepeat(booleanVal(value));
- } else if (command.equalsIgnoreCase("supportsSpeed")) {
- setSupportsSpeed(booleanVal(value));
- } else if (command.equalsIgnoreCase("powerRequirement")) {
- setPowerRequirement(intVal(value));
- } else if (command.equalsIgnoreCase("accuracy")) {
- setAccuracy(intVal(value));
- } else if (command.equalsIgnoreCase("trackspeed")) {
- setTrackSpeed(floatVal(value));
- } else {
- Log.e(LOG_TAG, "Unknown command \"" + command + "\"");
- }
- }
- } catch (IOException ioe) {
- Log.e(LOG_TAG, "IOException reading properties file " +
- propertiesFile.getPath(), ioe);
- } finally {
- try {
- if (br != null) {
- br.close();
- }
- } catch (IOException e) {
- Log.w(LOG_TAG, "IOException closing properties file " +
- propertiesFile.getPath(), e);
- }
- }
- }
-
- public TrackProvider(String name) {
- super(name);
- setTimes();
- }
-
- public TrackProvider(String name, File file) {
- this(name);
-
- String filename = file.getName();
- if (filename.endsWith("kml")) {
- readKml(file);
- } else if (filename.endsWith("nmea")) {
- readNmea(getName(), file);
- } else if (filename.endsWith("track")) {
- readTrack(file);
- } else {
- Log.e(LOG_TAG, "Can't initialize TrackProvider from file " +
- filename + " (not *kml, *nmea, or *track)");
- }
- setTimes();
- }
-
- private void setTimes() {
- mBaseTime = System.currentTimeMillis();
- if (mWaypoints.size() >= 2) {
- mMinTime = mWaypoints.get(0).getTime();
- mMaxTime = mWaypoints.get(mWaypoints.size() - 1).getTime();
- } else {
- mMinTime = mMaxTime = 0;
- }
- }
-
- private double interp(double d0, double d1, float frac) {
- return d0 + frac * (d1 - d0);
- }
-
- private void update() {
- // Don't update the position at all unless INTERVAL milliseconds
- // have passed since the last request
- long time = System.currentTimeMillis() - mBaseTime;
- if (time - mLastTime < INTERVAL) {
- return;
- }
-
- List<Waypoint> waypoints = mWaypoints;
- if (waypoints == null) {
- return;
- }
- int size = waypoints.size();
- if (size < 2) {
- return;
- }
-
- long t = time;
- if (t < mMinTime) {
- t = mMinTime;
- }
- if (mRepeat) {
- t -= mMinTime;
- long deltaT = mMaxTime - mMinTime;
- t %= 2 * deltaT;
- if (t > deltaT) {
- t = 2 * deltaT - t;
- }
- t += mMinTime;
- } else if (t > mMaxTime) {
- t = mMaxTime;
- }
-
- // Locate the time interval for the current time
- // We slide the window since we don't expect to move
- // much between calls
-
- Waypoint w0 = waypoints.get(mWaypointIndex);
- Waypoint w1 = waypoints.get(mWaypointIndex + 1);
-
- // If the right end of the current interval is too early,
- // move forward to the next waypoint
- while (t > w1.getTime()) {
- w0 = w1;
- w1 = waypoints.get(++mWaypointIndex + 1);
- }
- // If the left end of the current interval is too late,
- // move back to the previous waypoint
- while (t < w0.getTime()) {
- w1 = w0;
- w0 = waypoints.get(--mWaypointIndex);
- }
-
- // Now we know that w0.mTime <= t <= w1.mTime
- long w0Time = w0.getTime();
- long w1Time = w1.getTime();
- long dt = w1Time - w0Time;
-
- float frac = (dt == 0) ? 0 : ((float) (t - w0Time) / dt);
- mLatitude = interp(w0.getLatitude(), w1.getLatitude(), frac);
- mLongitude = interp(w0.getLongitude(), w1.getLongitude(), frac);
- mHasAltitude = w0.hasAltitude() && w1.hasAltitude();
- if (mSupportsAltitude && mHasAltitude) {
- mAltitude = interp(w0.getAltitude(), w1.getAltitude(), frac);
- }
- if (mSupportsBearing) {
- mHasBearing = frac <= 0.5f ? w0.hasBearing() : w1.hasBearing();
- if (mHasBearing) {
- mBearing = frac <= 0.5f ? w0.getBearing() : w1.getBearing();
- }
- }
- if (mSupportsSpeed) {
- mHasSpeed = frac <= 0.5f ? w0.hasSpeed() : w1.hasSpeed();
- if (mHasSpeed) {
- mSpeed = frac <= 0.5f ? w0.getSpeed() : w1.getSpeed();
- }
- }
- mLastTime = time;
- mTime = time;
- }
-
- public void setRequiresNetwork(boolean requiresNetwork) {
- mRequiresNetwork = requiresNetwork;
- }
-
- @Override public boolean requiresNetwork() {
- return mRequiresNetwork;
- }
-
- public void setRequiresSatellite(boolean requiresSatellite) {
- mRequiresSatellite = requiresSatellite;
- }
-
- @Override public boolean requiresSatellite() {
- return mRequiresSatellite;
- }
-
- public void setRequiresCell(boolean requiresCell) {
- mRequiresCell = requiresCell;
- }
-
- @Override public boolean requiresCell() {
- return mRequiresCell;
- }
-
- public void setHasMonetaryCost(boolean hasMonetaryCost) {
- mHasMonetaryCost = hasMonetaryCost;
- }
-
- @Override public boolean hasMonetaryCost() {
- return mHasMonetaryCost;
- }
-
- public void setSupportsAltitude(boolean supportsAltitude) {
- mSupportsAltitude = supportsAltitude;
- }
-
- @Override public boolean supportsAltitude() {
- return mSupportsAltitude;
- }
-
- public void setSupportsSpeed(boolean supportsSpeed) {
- mSupportsSpeed = supportsSpeed;
- }
-
- @Override public boolean supportsSpeed() {
- return mSupportsSpeed;
- }
-
- public void setSupportsBearing(boolean supportsBearing) {
- mSupportsBearing = supportsBearing;
- }
-
- @Override public boolean supportsBearing() {
- return mSupportsBearing;
- }
-
- public void setRepeat(boolean repeat) {
- mRepeat = repeat;
- }
-
- public void setPowerRequirement(int powerRequirement) {
- if (powerRequirement < Criteria.POWER_LOW ||
- powerRequirement > Criteria.POWER_HIGH) {
- throw new IllegalArgumentException("powerRequirement = " +
- powerRequirement);
- }
- mPowerRequirement = powerRequirement;
- }
-
- @Override public int getPowerRequirement() {
- return mPowerRequirement;
- }
-
- public void setAccuracy(int accuracy) {
- mAccuracy = accuracy;
- }
-
- @Override public int getAccuracy() {
- return mAccuracy;
- }
-
- public void setTrackSpeed(float trackSpeed) {
- mTrackSpeed = trackSpeed;
- }
-
- @Override public void enable() {
- mEnabled = true;
- }
-
- @Override public void disable() {
- mEnabled = false;
- }
-
- @Override public boolean isEnabled() {
- return mEnabled;
- }
-
- @Override public int getStatus(Bundle extras) {
- return AVAILABLE;
- }
-
- @Override public boolean getLocation(Location l) {
- if (mEnabled) {
- update();
- l.setProvider(getName());
- l.setTime(mTime + mBaseTime);
- l.setLatitude(mLatitude);
- l.setLongitude(mLongitude);
- if (mSupportsAltitude && mHasAltitude) {
- l.setAltitude(mAltitude);
- }
- if (mSupportsBearing && mHasBearing) {
- l.setBearing(mBearing);
- }
- if (mSupportsSpeed && mHasSpeed) {
- l.setSpeed(mSpeed);
- }
- if (mExtras != null) {
- l.setExtras(mExtras);
- }
- return true;
- } else {
- return false;
- }
- }
-
- public Location getInitialLocation() {
- return mInitialLocation;
- }
-}
-
-/**
- * A simple tuple of (time stamp, latitude, longitude, altitude), plus optional
- * extras.
- *
- * {@hide}
- */
-class Waypoint {
- public Location mLocation;
-
- public Waypoint(Location location) {
- mLocation = location;
- }
-
- public Waypoint(String providerName, long time, double latitude, double longitude,
- double altitude) {
- mLocation = new Location(providerName);
- mLocation.setTime(time);
- mLocation.setLatitude(latitude);
- mLocation.setLongitude(longitude);
- mLocation.setAltitude(altitude);
- }
-
- public long getTime() {
- return mLocation.getTime();
- }
-
- public double getLatitude() {
- return mLocation.getLatitude();
- }
-
- public double getLongitude() {
- return mLocation.getLongitude();
- }
-
- public boolean hasAltitude() {
- return mLocation.hasAltitude();
- }
-
- public double getAltitude() {
- return mLocation.getAltitude();
- }
-
- public boolean hasBearing() {
- return mLocation.hasBearing();
- }
-
- public void setBearing(float bearing) {
- mLocation.setBearing(bearing);
- }
-
- public float getBearing() {
- return mLocation.getBearing();
- }
-
- public boolean hasSpeed() {
- return mLocation.hasSpeed();
- }
-
- public void setSpeed(float speed) {
- mLocation.setSpeed(speed);
- }
-
- public float getSpeed() {
- return mLocation.getSpeed();
- }
-
- public Bundle getExtras() {
- return mLocation.getExtras();
- }
-
- public Location getLocation() {
- return new Location(mLocation);
- }
-
- @Override public String toString() {
- return "Waypoint[mLocation=" + mLocation + "]";
- }
-}