diff options
Diffstat (limited to 'location/java')
7 files changed, 757 insertions, 459 deletions
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index 1fac07c..628cb6b7 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -81,10 +81,6 @@ interface ILocationManager 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 installGeocodeProvider(IGeocodeProvider provider); - // for NI support boolean sendNiResponse(int notifId, int userResponse); } diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 6d7a23d..9027fc2 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -104,48 +104,6 @@ public class LocationManager { */ public static final String KEY_LOCATION_CHANGED = "location"; - public interface GeocodeProvider { - String getFromLocation(double latitude, double longitude, int maxResults, - GeocoderParams params, List<Address> addrs); - - String getFromLocationName(String locationName, - double lowerLeftLatitude, double lowerLeftLongitude, - double upperRightLatitude, double upperRightLongitude, int maxResults, - GeocoderParams params, List<Address> addrs); - } - - private static final class GeocodeProviderProxy extends IGeocodeProvider.Stub { - private GeocodeProvider mProvider; - - GeocodeProviderProxy(GeocodeProvider provider) { - mProvider = provider; - } - - /** - * This method is overridden to implement the - * {@link Geocoder#getFromLocation(double, double, int)} method. - * Classes implementing this method should not hold a reference to the params parameter. - */ - public String getFromLocation(double latitude, double longitude, int maxResults, - GeocoderParams params, List<Address> addrs) { - return mProvider.getFromLocation(latitude, longitude, maxResults, params, addrs); - } - - /** - * This method is overridden to implement the - * {@link Geocoder#getFromLocationName(String, int, double, double, double, double)} method. - * Classes implementing this method should not hold a reference to the params parameter. - */ - public String getFromLocationName(String locationName, - double lowerLeftLatitude, double lowerLeftLongitude, - double upperRightLatitude, double upperRightLongitude, int maxResults, - GeocoderParams params, List<Address> addrs) { - return mProvider.getFromLocationName(locationName, lowerLeftLatitude, - lowerLeftLongitude, upperRightLatitude, upperRightLongitude, - maxResults, params, addrs); - } - } - // Map from LocationListeners to their associated ListenerTransport objects private HashMap<LocationListener,ListenerTransport> mListeners = new HashMap<LocationListener,ListenerTransport>(); @@ -1395,75 +1353,6 @@ 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 provider. - * - * @param provider implementation of the location provider - * - * @return true if the command succeeds. - * - * Requires the android.permission.INSTALL_LOCATION_PROVIDER permission. - */ - public boolean installLocationProvider(LocationProviderImpl provider) { - return installLocationProvider(provider.getName(), provider.getInterface()); - } - - /** - * 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. - */ - public boolean installGeocodeProvider(GeocodeProvider provider) { - try { - mService.installGeocodeProvider(new GeocodeProviderProxy(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. - */ - public void reportLocation(Location location) { - try { - mService.reportLocation(location); - } catch (RemoteException e) { - Log.e(TAG, "RemoteException in reportLocation: ", e); - } - } /** * Used by NetInitiatedActivity to report user response diff --git a/location/java/android/location/LocationProviderImpl.java b/location/java/android/location/LocationProviderImpl.java deleted file mode 100644 index 7148a02..0000000 --- a/location/java/android/location/LocationProviderImpl.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (C) 2010 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.net.NetworkInfo; -import android.os.Bundle; - -/** - * An abstract superclass for location providers that are implemented - * outside of the core android platform. - * A LocationProviderImpl can be installed using the - * {@link LocationManager#installLocationProvider(LocationProviderImpl)} method. - * Installing a location provider requires the - * android.permission.INSTALL_LOCATION_PROVIDER permission. - */ -public abstract class LocationProviderImpl extends LocationProvider { - - private ILocationProvider.Stub mProvider = new ILocationProvider.Stub() { - - public boolean requiresNetwork() { - return LocationProviderImpl.this.requiresNetwork(); - } - - public boolean requiresSatellite() { - return LocationProviderImpl.this.requiresSatellite(); - } - - public boolean requiresCell() { - return LocationProviderImpl.this.requiresCell(); - } - - public boolean hasMonetaryCost() { - return LocationProviderImpl.this.hasMonetaryCost(); - } - - public boolean supportsAltitude() { - return LocationProviderImpl.this.supportsAltitude(); - } - - public boolean supportsSpeed() { - return LocationProviderImpl.this.supportsSpeed(); - } - - public boolean supportsBearing() { - return LocationProviderImpl.this.supportsBearing(); - } - - public int getPowerRequirement() { - return LocationProviderImpl.this.getPowerRequirement(); - } - - public int getAccuracy() { - return LocationProviderImpl.this.getAccuracy(); - } - - public void enable() { - LocationProviderImpl.this.enable(); - } - - public void disable() { - LocationProviderImpl.this.disable(); - } - - public int getStatus(Bundle extras) { - return LocationProviderImpl.this.getStatus(extras); - } - - public long getStatusUpdateTime() { - return LocationProviderImpl.this.getStatusUpdateTime(); - } - - public void enableLocationTracking(boolean enable) { - LocationProviderImpl.this.enableLocationTracking(enable); - } - - public void setMinTime(long minTime) { - LocationProviderImpl.this.setMinTime(minTime); - } - - public void updateNetworkState(int state, NetworkInfo info) { - LocationProviderImpl.this.updateNetworkState(state, info); - } - - public void updateLocation(Location location) { - LocationProviderImpl.this.updateLocation(location); - } - - public boolean sendExtraCommand(String command, Bundle extras) { - return LocationProviderImpl.this.sendExtraCommand(command, extras); - } - - public void addListener(int uid) { - LocationProviderImpl.this.addListener(uid); - } - - public void removeListener(int uid) { - LocationProviderImpl.this.removeListener(uid); - } - }; - - public LocationProviderImpl(String name) { - super(name); - } - - /** - * {@hide} - */ - /* package */ ILocationProvider getInterface() { - return mProvider; - } - - /** - * Enables the location provider - */ - public abstract void enable(); - - /** - * Disables the location provider - */ - public abstract void disable(); - - /** - * 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 SystemClock.elapsedRealtime()}. - * 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 abstract long getStatusUpdateTime(); - - /** - * 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 abstract void enableLocationTracking(boolean enable); - - /** - * 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 abstract void setMinTime(long minTime); - - /** - * 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 abstract void updateNetworkState(int state, NetworkInfo info); - - /** - * Informs the provider when a new location has been computed by a different - * location provider. This is intended to be used as aiding data for the - * receiving provider. - * - * @param location new location from other location provider - */ - public abstract void updateLocation(Location location); - - /** - * 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 abstract boolean sendExtraCommand(String command, Bundle extras); - - /** - * Notifies the location provider when a new client is listening for locations. - * - * @param uid user ID of the new client. - */ - public abstract void addListener(int uid); - - /** - * Notifies the location provider when a client is no longer listening for locations. - * - * @param uid user ID of the client no longer listening. - */ - public abstract void removeListener(int uid); -} - diff --git a/location/java/android/location/provider/GeocodeProvider.java b/location/java/android/location/provider/GeocodeProvider.java new file mode 100644 index 0000000..86376a7 --- /dev/null +++ b/location/java/android/location/provider/GeocodeProvider.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2010 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.provider; + +import android.os.IBinder; + +import android.location.Address; +import android.location.GeocoderParams; +import android.location.IGeocodeProvider; + +import java.util.List; + +/** + * An abstract superclass for geocode providers that are implemented + * outside of the core android platform. + * Geocode providers can be implemented as services and return the result of + * {@link GeocodeProvider#getBinder()} in its getBinder() method. + * + * @hide + */ +public abstract class GeocodeProvider { + + private IGeocodeProvider.Stub mProvider = new IGeocodeProvider.Stub() { + public String getFromLocation(double latitude, double longitude, int maxResults, + GeocoderParams params, List<Address> addrs) { + return GeocodeProvider.this.onGetFromLocation(latitude, longitude, maxResults, + params, addrs); + } + + public String getFromLocationName(String locationName, + double lowerLeftLatitude, double lowerLeftLongitude, + double upperRightLatitude, double upperRightLongitude, int maxResults, + GeocoderParams params, List<Address> addrs) { + return GeocodeProvider.this.onGetFromLocationName(locationName, lowerLeftLatitude, + lowerLeftLongitude, upperRightLatitude, upperRightLongitude, + maxResults, params, addrs); + } + }; + + /** + * This method is overridden to implement the + * {@link Geocoder#getFromLocation(double, double, int)} method. + * Classes implementing this method should not hold a reference to the params parameter. + */ + public abstract String onGetFromLocation(double latitude, double longitude, int maxResults, + GeocoderParams params, List<Address> addrs); + + /** + * This method is overridden to implement the + * {@link Geocoder#getFromLocationName(String, int, double, double, double, double)} method. + * Classes implementing this method should not hold a reference to the params parameter. + */ + public abstract String onGetFromLocationName(String locationName, + double lowerLeftLatitude, double lowerLeftLongitude, + double upperRightLatitude, double upperRightLongitude, int maxResults, + GeocoderParams params, List<Address> addrs); + + /** + * Returns the Binder interface for the geocode provider. + * This is intended to be used for the onBind() method of + * a service that implements a geocoder service. + * + * @return the IBinder instance for the provider + */ + public IBinder getBinder() { + return mProvider; + } +} + diff --git a/location/java/android/location/provider/LocationProvider.java b/location/java/android/location/provider/LocationProvider.java new file mode 100644 index 0000000..0d028c0 --- /dev/null +++ b/location/java/android/location/provider/LocationProvider.java @@ -0,0 +1,333 @@ +/* + * Copyright (C) 2010 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.provider; + +import android.content.Context; +import android.net.NetworkInfo; +import android.location.ILocationManager; +import android.location.ILocationProvider; +import android.location.Location; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; + +/** + * An abstract superclass for location providers that are implemented + * outside of the core android platform. + * Location providers can be implemented as services and return the result of + * {@link LocationProvider#getBinder()} in its getBinder() method. + * + * @hide + */ +public abstract class LocationProvider { + + private static final String TAG = "LocationProvider"; + + private ILocationManager mLocationManager; + + private ILocationProvider.Stub mProvider = new ILocationProvider.Stub() { + + public boolean requiresNetwork() { + return LocationProvider.this.onRequiresNetwork(); + } + + public boolean requiresSatellite() { + return LocationProvider.this.onRequiresSatellite(); + } + + public boolean requiresCell() { + return LocationProvider.this.onRequiresCell(); + } + + public boolean hasMonetaryCost() { + return LocationProvider.this.onHasMonetaryCost(); + } + + public boolean supportsAltitude() { + return LocationProvider.this.onSupportsAltitude(); + } + + public boolean supportsSpeed() { + return LocationProvider.this.onSupportsSpeed(); + } + + public boolean supportsBearing() { + return LocationProvider.this.onSupportsBearing(); + } + + public int getPowerRequirement() { + return LocationProvider.this.onGetPowerRequirement(); + } + + public int getAccuracy() { + return LocationProvider.this.onGetAccuracy(); + } + + public void enable() { + LocationProvider.this.onEnable(); + } + + public void disable() { + LocationProvider.this.onDisable(); + } + + public int getStatus(Bundle extras) { + return LocationProvider.this.onGetStatus(extras); + } + + public long getStatusUpdateTime() { + return LocationProvider.this.onGetStatusUpdateTime(); + } + + public void enableLocationTracking(boolean enable) { + LocationProvider.this.onEnableLocationTracking(enable); + } + + public void setMinTime(long minTime) { + LocationProvider.this.onSetMinTime(minTime); + } + + public void updateNetworkState(int state, NetworkInfo info) { + LocationProvider.this.onUpdateNetworkState(state, info); + } + + public void updateLocation(Location location) { + LocationProvider.this.onUpdateLocation(location); + } + + public boolean sendExtraCommand(String command, Bundle extras) { + return LocationProvider.this.onSendExtraCommand(command, extras); + } + + public void addListener(int uid) { + LocationProvider.this.onAddListener(uid); + } + + public void removeListener(int uid) { + LocationProvider.this.onRemoveListener(uid); + } + }; + + public LocationProvider() { + IBinder b = ServiceManager.getService(Context.LOCATION_SERVICE); + mLocationManager = ILocationManager.Stub.asInterface(b); + } + + /** + * {@hide} + */ + /* package */ ILocationProvider getInterface() { + return mProvider; + } + + /** + * Returns the Binder interface for the location provider. + * This is intended to be used for the onBind() method of + * a service that implements a location provider service. + * + * @return the IBinder instance for the provider + */ + public IBinder getBinder() { + return mProvider; + } + + /** + * Used by the location provider to report new locations. + * + * @param location new Location to report + * + * Requires the android.permission.INSTALL_LOCATION_PROVIDER permission. + */ + public void reportLocation(Location location) { + try { + mLocationManager.reportLocation(location); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in reportLocation: ", e); + } + } + + /** + * Returns true if the provider requires access to a + * data network (e.g., the Internet), false otherwise. + */ + public abstract boolean onRequiresNetwork(); + + /** + * Returns true if the provider requires access to a + * satellite-based positioning system (e.g., GPS), false + * otherwise. + */ + public abstract boolean onRequiresSatellite(); + + /** + * Returns true if the provider requires access to an appropriate + * cellular network (e.g., to make use of cell tower IDs), false + * otherwise. + */ + public abstract boolean onRequiresCell(); + + /** + * Returns true if the use of this provider may result in a + * monetary charge to the user, false if use is free. It is up to + * each provider to give accurate information. + */ + public abstract boolean onHasMonetaryCost(); + + /** + * Returns true if the provider is able to provide altitude + * information, false otherwise. A provider that reports altitude + * under most circumstances but may occassionally not report it + * should return true. + */ + public abstract boolean onSupportsAltitude(); + + /** + * Returns true if the provider is able to provide speed + * information, false otherwise. A provider that reports speed + * under most circumstances but may occassionally not report it + * should return true. + */ + public abstract boolean onSupportsSpeed(); + + /** + * Returns true if the provider is able to provide bearing + * information, false otherwise. A provider that reports bearing + * under most circumstances but may occassionally not report it + * should return true. + */ + public abstract boolean onSupportsBearing(); + + /** + * Returns the power requirement for this provider. + * + * @return the power requirement for this provider, as one of the + * constants Criteria.POWER_REQUIREMENT_*. + */ + public abstract int onGetPowerRequirement(); + + /** + * Returns a constant describing horizontal accuracy of this provider. + * If the provider returns finer grain or exact location, + * {@link Criteria#ACCURACY_FINE} is returned, otherwise if the + * location is only approximate then {@link Criteria#ACCURACY_COARSE} + * is returned. + */ + public abstract int onGetAccuracy(); + + /** + * Enables the location provider + */ + public abstract void onEnable(); + + /** + * Disables the location provider + */ + public abstract void onDisable(); + + /** + * 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 onGetStatus(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 SystemClock.elapsedRealtime()}. + * 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 abstract long onGetStatusUpdateTime(); + + /** + * 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 abstract void onEnableLocationTracking(boolean enable); + + /** + * 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 abstract void onSetMinTime(long minTime); + + /** + * 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 abstract void onUpdateNetworkState(int state, NetworkInfo info); + + /** + * Informs the provider when a new location has been computed by a different + * location provider. This is intended to be used as aiding data for the + * receiving provider. + * + * @param location new location from other location provider + */ + public abstract void onUpdateLocation(Location location); + + /** + * 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 abstract boolean onSendExtraCommand(String command, Bundle extras); + + /** + * Notifies the location provider when a new client is listening for locations. + * + * @param uid user ID of the new client. + */ + public abstract void onAddListener(int uid); + + /** + * Notifies the location provider when a client is no longer listening for locations. + * + * @param uid user ID of the client no longer listening. + */ + public abstract void onRemoveListener(int uid); +} + diff --git a/location/java/com/android/internal/location/GeocoderProxy.java b/location/java/com/android/internal/location/GeocoderProxy.java new file mode 100644 index 0000000..b06297b --- /dev/null +++ b/location/java/com/android/internal/location/GeocoderProxy.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.location; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.location.Address; +import android.location.GeocoderParams; +import android.location.IGeocodeProvider; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.SystemClock; +import android.util.Log; + +import java.util.List; + +/** + * A class for proxying IGeocodeProvider implementations. + * + * {@hide} + */ +public class GeocoderProxy { + + private static final String TAG = "GeocoderProxy"; + + private final Context mContext; + private final Intent mIntent; + private final Connection mServiceConnection = new Connection(); + private IGeocodeProvider mProvider; + + public GeocoderProxy(Context context, String serviceName) { + mContext = context; + mIntent = new Intent(serviceName); + mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE); + } + + private class Connection implements ServiceConnection { + public void onServiceConnected(ComponentName className, IBinder service) { + Log.d(TAG, "onServiceConnected " + className); + synchronized (this) { + mProvider = IGeocodeProvider.Stub.asInterface(service); + } + } + + public void onServiceDisconnected(ComponentName className) { + Log.d(TAG, "onServiceDisconnected " + className); + synchronized (this) { + mProvider = null; + } + } + } + + public String getFromLocation(double latitude, double longitude, int maxResults, + GeocoderParams params, List<Address> addrs) { + IGeocodeProvider provider; + synchronized (mServiceConnection) { + provider = mProvider; + } + if (provider != null) { + try { + return provider.getFromLocation(latitude, longitude, maxResults, + params, addrs); + } catch (RemoteException e) { + Log.e(TAG, "getFromLocation failed", e); + } + } + return "Service not Available"; + } + + public String getFromLocationName(String locationName, + double lowerLeftLatitude, double lowerLeftLongitude, + double upperRightLatitude, double upperRightLongitude, int maxResults, + GeocoderParams params, List<Address> addrs) { + IGeocodeProvider provider; + synchronized (mServiceConnection) { + provider = mProvider; + } + if (provider != null) { + try { + return provider.getFromLocationName(locationName, lowerLeftLatitude, + lowerLeftLongitude, upperRightLatitude, upperRightLongitude, + maxResults, params, addrs); + } catch (RemoteException e) { + Log.e(TAG, "getFromLocationName failed", e); + } + } + return "Service not Available"; + } +} diff --git a/location/java/com/android/internal/location/LocationProviderProxy.java b/location/java/com/android/internal/location/LocationProviderProxy.java index 2e0be89..361104f 100644 --- a/location/java/com/android/internal/location/LocationProviderProxy.java +++ b/location/java/com/android/internal/location/LocationProviderProxy.java @@ -16,155 +16,229 @@ package com.android.internal.location; -import android.location.Address; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; import android.location.ILocationProvider; import android.location.Location; -import android.location.LocationManager; import android.net.NetworkInfo; import android.os.Bundle; +import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; +import android.os.SystemClock; import android.util.Log; -import java.util.List; - /** - * A class for proxying remote ILocationProvider implementations. + * A class for proxying ILocationProvider implementations. * * {@hide} */ -public class LocationProviderProxy implements IBinder.DeathRecipient { +public class LocationProviderProxy { private static final String TAG = "LocationProviderProxy"; + private final Context mContext; private final String mName; - private final ILocationProvider mProvider; + private ILocationProvider mProvider; + private Intent mIntent; + private Handler mHandler; + private final Connection mServiceConnection = new Connection(); + + // cached values set by the location manager private boolean mLocationTracking = false; private boolean mEnabled = false; - private long mMinTime = 0; - private boolean mDead; + private long mMinTime = -1; + private int mNetworkState; + private NetworkInfo mNetworkInfo; - public LocationProviderProxy(String name, ILocationProvider provider) { + // for caching requiresNetwork, requiresSatellite, etc. + private DummyLocationProvider mCachedAttributes; + + // constructor for proxying built-in location providers + public LocationProviderProxy(Context context, String name, ILocationProvider provider) { + mContext = context; mName = name; mProvider = provider; - try { - provider.asBinder().linkToDeath(this, 0); - } catch (RemoteException e) { - Log.e(TAG, "linkToDeath failed", e); - mDead = true; - } } - public void unlinkProvider() { - if (mProvider != null) { - mProvider.asBinder().unlinkToDeath(this, 0); + // constructor for proxying location providers implemented in a separate service + public LocationProviderProxy(Context context, String name, String serviceName, + Handler handler) { + mContext = context; + mName = name; + mIntent = new Intent(serviceName); + mHandler = handler; + mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE); + } + + private class Connection implements ServiceConnection { + public void onServiceConnected(ComponentName className, IBinder service) { + Log.d(TAG, "LocationProviderProxy.onServiceConnected " + className); + synchronized (this) { + mProvider = ILocationProvider.Stub.asInterface(service); + if (mProvider != null) { + mHandler.post(mServiceConnectedTask); + } + } + } + + public void onServiceDisconnected(ComponentName className) { + Log.d(TAG, "LocationProviderProxy.onServiceDisconnected " + className); + synchronized (this) { + mProvider = null; + } } } + private Runnable mServiceConnectedTask = new Runnable() { + public void run() { + ILocationProvider provider; + synchronized (mServiceConnection) { + provider = mProvider; + if (provider == null) { + return; + } + } + + if (mCachedAttributes == null) { + try { + mCachedAttributes = new DummyLocationProvider(mName); + mCachedAttributes.setRequiresNetwork(provider.requiresNetwork()); + mCachedAttributes.setRequiresSatellite(provider.requiresSatellite()); + mCachedAttributes.setRequiresCell(provider.requiresCell()); + mCachedAttributes.setHasMonetaryCost(provider.hasMonetaryCost()); + mCachedAttributes.setSupportsAltitude(provider.supportsAltitude()); + mCachedAttributes.setSupportsSpeed(provider.supportsSpeed()); + mCachedAttributes.setSupportsBearing(provider.supportsBearing()); + mCachedAttributes.setPowerRequirement(provider.getPowerRequirement()); + mCachedAttributes.setAccuracy(provider.getAccuracy()); + } catch (RemoteException e) { + mCachedAttributes = null; + } + } + + // resend previous values from the location manager if the service has restarted + try { + if (mEnabled) { + provider.enable(); + } + if (mLocationTracking) { + provider.enableLocationTracking(true); + } + if (mMinTime >= 0) { + provider.setMinTime(mMinTime); + } + if (mNetworkInfo != null) { + provider.updateNetworkState(mNetworkState, mNetworkInfo); + } + } catch (RemoteException e) { + } + } + }; + 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); + if (mCachedAttributes != null) { + return mCachedAttributes.requiresNetwork(); + } else { return false; } } public boolean requiresSatellite() { - try { - return mProvider.requiresSatellite(); - } catch (RemoteException e) { - Log.e(TAG, "requiresSatellite failed", e); + if (mCachedAttributes != null) { + return mCachedAttributes.requiresSatellite(); + } else { return false; } } public boolean requiresCell() { - try { - return mProvider.requiresCell(); - } catch (RemoteException e) { - Log.e(TAG, "requiresCell failed", e); + if (mCachedAttributes != null) { + return mCachedAttributes.requiresCell(); + } else { return false; } } public boolean hasMonetaryCost() { - try { - return mProvider.hasMonetaryCost(); - } catch (RemoteException e) { - Log.e(TAG, "hasMonetaryCost failed", e); + if (mCachedAttributes != null) { + return mCachedAttributes.hasMonetaryCost(); + } else { return false; } } public boolean supportsAltitude() { - try { - return mProvider.supportsAltitude(); - } catch (RemoteException e) { - Log.e(TAG, "supportsAltitude failed", e); + if (mCachedAttributes != null) { + return mCachedAttributes.supportsAltitude(); + } else { return false; } } public boolean supportsSpeed() { - try { - return mProvider.supportsSpeed(); - } catch (RemoteException e) { - Log.e(TAG, "supportsSpeed failed", e); + if (mCachedAttributes != null) { + return mCachedAttributes.supportsSpeed(); + } else { return false; } } public boolean supportsBearing() { - try { - return mProvider.supportsBearing(); - } catch (RemoteException e) { - Log.e(TAG, "supportsBearing failed", e); + if (mCachedAttributes != null) { + return mCachedAttributes.supportsBearing(); + } else { return false; } } public int getPowerRequirement() { - try { - return mProvider.getPowerRequirement(); - } catch (RemoteException e) { - Log.e(TAG, "getPowerRequirement failed", e); - return 0; + if (mCachedAttributes != null) { + return mCachedAttributes.getPowerRequirement(); + } else { + return -1; } } public int getAccuracy() { - try { - return mProvider.getAccuracy(); - } catch (RemoteException e) { - Log.e(TAG, "getAccuracy failed", e); - return 0; + if (mCachedAttributes != null) { + return mCachedAttributes.getAccuracy(); + } else { + return -1; } } public void enable() { - try { - mProvider.enable(); - mEnabled = true; - } catch (RemoteException e) { - Log.e(TAG, "enable failed", e); + mEnabled = true; + ILocationProvider provider; + synchronized (mServiceConnection) { + provider = mProvider; + } + if (provider != null) { + try { + provider.enable(); + } catch (RemoteException e) { + } } } public void disable() { - try { - mProvider.disable(); - mEnabled = false; - } catch (RemoteException e) { - Log.e(TAG, "disable failed", e); + mEnabled = false; + ILocationProvider provider; + synchronized (mServiceConnection) { + provider = mProvider; + } + if (provider != null) { + try { + provider.disable(); + } catch (RemoteException e) { + } } } @@ -173,22 +247,32 @@ public class LocationProviderProxy implements IBinder.DeathRecipient { } public int getStatus(Bundle extras) { - try { - return mProvider.getStatus(extras); - } catch (RemoteException e) { - Log.e(TAG, "getStatus failed", e); - return 0; + ILocationProvider provider; + synchronized (mServiceConnection) { + provider = mProvider; } + if (provider != null) { + try { + return provider.getStatus(extras); + } catch (RemoteException e) { + } + } + return 0; } public long getStatusUpdateTime() { - try { - return mProvider.getStatusUpdateTime(); - } catch (RemoteException e) { - Log.e(TAG, "getStatusUpdateTime failed", e); - return 0; + ILocationProvider provider; + synchronized (mServiceConnection) { + provider = mProvider; } - } + if (provider != null) { + try { + return provider.getStatusUpdateTime(); + } catch (RemoteException e) { + } + } + return 0; + } public boolean isLocationTracking() { return mLocationTracking; @@ -196,10 +280,18 @@ public class LocationProviderProxy implements IBinder.DeathRecipient { public void enableLocationTracking(boolean enable) { mLocationTracking = enable; - try { - mProvider.enableLocationTracking(enable); - } catch (RemoteException e) { - Log.e(TAG, "enableLocationTracking failed", e); + if (!enable) { + mMinTime = -1; + } + ILocationProvider provider; + synchronized (mServiceConnection) { + provider = mProvider; + } + if (provider != null) { + try { + provider.enableLocationTracking(enable); + } catch (RemoteException e) { + } } } @@ -208,58 +300,84 @@ public class LocationProviderProxy implements IBinder.DeathRecipient { } public void setMinTime(long minTime) { - mMinTime = minTime; - try { - mProvider.setMinTime(minTime); - } catch (RemoteException e) { - Log.e(TAG, "setMinTime failed", e); + mMinTime = minTime; + ILocationProvider provider; + synchronized (mServiceConnection) { + provider = mProvider; + } + if (provider != null) { + try { + provider.setMinTime(minTime); + } catch (RemoteException e) { + } } } public void updateNetworkState(int state, NetworkInfo info) { - try { - mProvider.updateNetworkState(state, info); - } catch (RemoteException e) { - Log.e(TAG, "updateNetworkState failed", e); + mNetworkState = state; + mNetworkInfo = info; + ILocationProvider provider; + synchronized (mServiceConnection) { + provider = mProvider; + } + if (provider != null) { + try { + provider.updateNetworkState(state, info); + } catch (RemoteException e) { + } } } public void updateLocation(Location location) { - try { - mProvider.updateLocation(location); - } catch (RemoteException e) { - Log.e(TAG, "updateLocation failed", e); + ILocationProvider provider; + synchronized (mServiceConnection) { + provider = mProvider; + } + if (provider != null) { + try { + provider.updateLocation(location); + } catch (RemoteException 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; + ILocationProvider provider; + synchronized (mServiceConnection) { + provider = mProvider; } + if (provider != null) { + try { + provider.sendExtraCommand(command, extras); + } catch (RemoteException e) { + } + } + return false; } public void addListener(int uid) { - try { - mProvider.addListener(uid); - } catch (RemoteException e) { - Log.e(TAG, "addListener failed", e); + ILocationProvider provider; + synchronized (mServiceConnection) { + provider = mProvider; + } + if (provider != null) { + try { + provider.addListener(uid); + } catch (RemoteException e) { + } } } public void removeListener(int uid) { - try { - mProvider.removeListener(uid); - } catch (RemoteException e) { - Log.e(TAG, "removeListener failed", e); + ILocationProvider provider; + synchronized (mServiceConnection) { + provider = mProvider; + } + if (provider != null) { + try { + provider.removeListener(uid); + } catch (RemoteException e) { + } } - } - - public void binderDied() { - Log.w(TAG, "Location Provider " + mName + " died"); - mDead = true; - mProvider.asBinder().unlinkToDeath(this, 0); } } |