diff options
author | Mike Lockwood <lockwood@android.com> | 2010-01-25 22:46:13 -0500 |
---|---|---|
committer | Mike Lockwood <lockwood@android.com> | 2010-02-08 23:20:27 -0500 |
commit | 628fd6d9c11ed9806abebf34bc986247c106328f (patch) | |
tree | 402876b69159436587770bc8754f6a66d02326ed /location/java | |
parent | 53bd2522ca7767f46646606123b6e2689b811850 (diff) | |
download | frameworks_base-628fd6d9c11ed9806abebf34bc986247c106328f.zip frameworks_base-628fd6d9c11ed9806abebf34bc986247c106328f.tar.gz frameworks_base-628fd6d9c11ed9806abebf34bc986247c106328f.tar.bz2 |
Network Location unbundling:
The network location and geocode provider services are now started on demand
and their interfaces are now retrieved via bindService().
Remove obsolete LocationManager installLocationProvider() and installGeocodeProvider() methods.
Add abstract class android.location.provider.GeocodeProvider to provide a public wrapper to
the IGeocodeProvider Binder interface. Replaces the LocationManager.GeocodeProvider interface.
Rename LocationProviderImpl to android.location.provider.LocationProvider.
Move LocationManager.reportLocation() to android.location.provider.LocationProvider,
so all methods related to external location providers are now all in one class.
Avoid calling from the Location Manager Service into providers that are disabled so we
do not start the network location service unnecessarily.
Change-Id: If3ed2d5d62b83ba508006711d575cad09f4a0007
Signed-off-by: Mike Lockwood <lockwood@android.com>
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); } } |