diff options
Diffstat (limited to 'location')
20 files changed, 1711 insertions, 872 deletions
diff --git a/location/java/android/location/Criteria.java b/location/java/android/location/Criteria.java index 1f3fb7a..6258a43 100644 --- a/location/java/android/location/Criteria.java +++ b/location/java/android/location/Criteria.java @@ -24,7 +24,9 @@ import android.os.Parcelable; * location provider. Providers maybe ordered according to accuracy, * power usage, ability to report altitude, speed, * and bearing, and monetary cost. + * @deprecated {@link LocationRequest} instead */ +@Deprecated public class Criteria implements Parcelable { /** * A constant indicating that the application does not choose to @@ -326,6 +328,7 @@ public class Criteria implements Parcelable { public static final Parcelable.Creator<Criteria> CREATOR = new Parcelable.Creator<Criteria>() { + @Override public Criteria createFromParcel(Parcel in) { Criteria c = new Criteria(); c.mHorizontalAccuracy = in.readInt(); @@ -340,15 +343,18 @@ public class Criteria implements Parcelable { return c; } + @Override public Criteria[] newArray(int size) { return new Criteria[size]; } }; + @Override public int describeContents() { return 0; } + @Override public void writeToParcel(Parcel parcel, int flags) { parcel.writeInt(mHorizontalAccuracy); parcel.writeInt(mVerticalAccuracy); @@ -360,4 +366,43 @@ public class Criteria implements Parcelable { parcel.writeInt(mSpeedRequired ? 1 : 0); parcel.writeInt(mCostAllowed ? 1 : 0); } + + private static String powerToString(int power) { + switch (power) { + case NO_REQUIREMENT: + return "NO_REQ"; + case POWER_LOW: + return "LOW"; + case POWER_MEDIUM: + return "MEDIUM"; + case POWER_HIGH: + return "HIGH"; + default: + return "???"; + } + } + + private static String accuracyToString(int accuracy) { + switch (accuracy) { + case NO_REQUIREMENT: + return "---"; + case ACCURACY_HIGH: + return "HIGH"; + case ACCURACY_MEDIUM: + return "MEDIUM"; + case ACCURACY_LOW: + return "LOW"; + default: + return "???"; + } + } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + s.append("Criteria[power=").append(powerToString(mPowerRequirement)); + s.append(" acc=").append(accuracyToString(mHorizontalAccuracy)); + s.append(']'); + return s.toString(); + } } diff --git a/location/java/android/location/Geofence.aidl b/location/java/android/location/Geofence.aidl new file mode 100644 index 0000000..a5c6aa0 --- /dev/null +++ b/location/java/android/location/Geofence.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2012, 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; + +parcelable Geofence; diff --git a/location/java/android/location/Geofence.java b/location/java/android/location/Geofence.java new file mode 100644 index 0000000..353a1ca --- /dev/null +++ b/location/java/android/location/Geofence.java @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2012 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.Parcel; +import android.os.Parcelable; + +/** + * Represents a Geofence + */ +public final class Geofence implements Parcelable { + /** @hide */ + public static final int TYPE_HORIZONTAL_CIRCLE = 1; + + private final int mType; + private final double mLatitude; + private final double mLongitude; + private final float mRadius; + + /** + * Create a horizontal, circular geofence. + * @param latitude latitude in degrees + * @param longitude longitude in degrees + * @param radius radius in meters + * @return a new geofence + * @throws IllegalArgumentException if any parameters are out of range + */ + public static Geofence createCircle(double latitude, double longitude, float radius) { + return new Geofence(latitude, longitude, radius); + } + + private Geofence(double latitude, double longitude, float radius) { + checkRadius(radius); + checkLatLong(latitude, longitude); + mType = TYPE_HORIZONTAL_CIRCLE; + mLatitude = latitude; + mLongitude = longitude; + mRadius = radius; + } + + /** @hide */ + public int getType() { + return mType; + } + + /** @hide */ + public double getLatitude() { + return mLatitude; + } + + /** @hide */ + public double getLongitude() { + return mLongitude; + } + + /** @hide */ + public float getRadius() { + return mRadius; + } + + private static void checkRadius(float radius) { + if (radius <= 0) { + throw new IllegalArgumentException("invalid radius: " + radius); + } + } + + private static void checkLatLong(double latitude, double longitude) { + if (latitude > 90.0 || latitude < -90.0) { + throw new IllegalArgumentException("invalid latitude: " + latitude); + } + if (longitude > 180.0 || longitude < -180.0) { + throw new IllegalArgumentException("invalid longitude: " + longitude); + } + } + + private static void checkType(int type) { + if (type != TYPE_HORIZONTAL_CIRCLE) { + throw new IllegalArgumentException("invalid type: " + type); + } + } + + public static final Parcelable.Creator<Geofence> CREATOR = new Parcelable.Creator<Geofence>() { + @Override + public Geofence createFromParcel(Parcel in) { + int type = in.readInt(); + double latitude = in.readDouble(); + double longitude = in.readDouble(); + float radius = in.readFloat(); + checkType(type); + return Geofence.createCircle(latitude, longitude, radius); + } + @Override + public Geofence[] newArray(int size) { + return new Geofence[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeInt(mType); + parcel.writeDouble(mLatitude); + parcel.writeDouble(mLongitude); + parcel.writeFloat(mRadius); + } + + private static String typeToString(int type) { + switch (type) { + case TYPE_HORIZONTAL_CIRCLE: + return "CIRCLE"; + default: + checkType(type); + return null; + } + } + + @Override + public String toString() { + return String.format("Geofence[%s %.6f, %.6f %.0fm]", + typeToString(mType), mLatitude, mLongitude, mRadius); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(mLatitude); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(mLongitude); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + Float.floatToIntBits(mRadius); + result = prime * result + mType; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof Geofence)) + return false; + Geofence other = (Geofence) obj; + if (mRadius != other.mRadius) + return false; + if (mLatitude != other.mLatitude) + return false; + if (mLongitude != other.mLongitude) + return false; + if (mType != other.mType) + return false; + return true; + } +} diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index 47b7adf..a2ce606 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -20,53 +20,36 @@ import android.app.PendingIntent; import android.location.Address; import android.location.Criteria; import android.location.GeocoderParams; +import android.location.Geofence; import android.location.IGeocodeProvider; import android.location.IGpsStatusListener; import android.location.ILocationListener; import android.location.Location; +import android.location.LocationRequest; import android.os.Bundle; +import com.android.internal.location.ProviderProperties; + /** * System private API for talking with the location service. * - * {@hide} + * @hide */ interface ILocationManager { - List<String> getAllProviders(); - List<String> getProviders(in Criteria criteria, boolean enabledOnly); - String getBestProvider(in Criteria criteria, boolean enabledOnly); - boolean providerMeetsCriteria(String provider, in Criteria criteria); + void requestLocationUpdates(in LocationRequest request, in ILocationListener listener, + in PendingIntent intent, String packageName); + void removeUpdates(in ILocationListener listener, in PendingIntent intent, String packageName); + + void requestGeofence(in LocationRequest request, in Geofence geofence, + in PendingIntent intent, String packageName); + void removeGeofence(in Geofence fence, in PendingIntent intent, String packageName); - void requestLocationUpdates(String provider, in Criteria criteria, long minTime, float minDistance, - boolean singleShot, in ILocationListener listener); - void requestLocationUpdatesPI(String provider, in Criteria criteria, long minTime, float minDistance, - boolean singleShot, in PendingIntent intent); - void removeUpdates(in ILocationListener listener); - void removeUpdatesPI(in PendingIntent intent); + Location getLastLocation(in LocationRequest request); 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, - long expiration, in PendingIntent intent, in String packageName); - void removeProximityAlert(in PendingIntent intent); - - Bundle getProviderInfo(String provider); - boolean isProviderEnabled(String provider); - - Location getLastKnownLocation(String provider); - - // Used by location providers to tell the location manager when it has a new location. - // Passive is true if the location is coming from the passive provider, in which case - // it need not be shared with other providers. - void reportLocation(in Location location, boolean passive); - boolean geocoderIsPresent(); String getFromLocation(double latitude, double longitude, int maxResults, in GeocoderParams params, out List<Address> addrs); @@ -75,9 +58,17 @@ interface ILocationManager double upperRightLatitude, double upperRightLongitude, int maxResults, in GeocoderParams params, out List<Address> addrs); - void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite, - boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude, - boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy); + boolean sendNiResponse(int notifId, int userResponse); + + // --- deprecated --- + List<String> getAllProviders(); + List<String> getProviders(in Criteria criteria, boolean enabledOnly); + String getBestProvider(in Criteria criteria, boolean enabledOnly); + boolean providerMeetsCriteria(String provider, in Criteria criteria); + ProviderProperties getProviderProperties(String provider); + boolean isProviderEnabled(String provider); + + void addTestProvider(String name, in ProviderProperties properties); void removeTestProvider(String provider); void setTestProviderLocation(String provider, in Location loc); void clearTestProviderLocation(String provider); @@ -86,6 +77,17 @@ interface ILocationManager void setTestProviderStatus(String provider, int status, in Bundle extras, long updateTime); void clearTestProviderStatus(String provider); - // for NI support - boolean sendNiResponse(int notifId, int userResponse); + boolean sendExtraCommand(String provider, String command, inout Bundle extras); + + // --- internal --- + + // Used by location providers to tell the location manager when it has a new location. + // Passive is true if the location is coming from the passive provider, in which case + // it need not be shared with other providers. + void reportLocation(in Location location, boolean passive); + + // for reporting callback completion + void locationCallbackFinished(ILocationListener listener); + + } diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java index 5ad60ab..ece4500 100644 --- a/location/java/android/location/Location.java +++ b/location/java/android/location/Location.java @@ -21,6 +21,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; import android.util.Printer; +import android.util.TimeUtils; import java.text.DecimalFormat; import java.util.StringTokenizer; @@ -84,17 +85,6 @@ public class Location implements Parcelable { // Scratchpad private float[] mResults = new float[2]; - public void dump(Printer pw, String prefix) { - pw.println(prefix + "mProvider=" + mProvider + " mTime=" + mTime); - pw.println(prefix + "mElapsedRealtimeNano=" + mElapsedRealtimeNano); - pw.println(prefix + "mLatitude=" + mLatitude + " mLongitude=" + mLongitude); - pw.println(prefix + "mHasAltitude=" + mHasAltitude + " mAltitude=" + mAltitude); - pw.println(prefix + "mHasSpeed=" + mHasSpeed + " mSpeed=" + mSpeed); - pw.println(prefix + "mHasBearing=" + mHasBearing + " mBearing=" + mBearing); - pw.println(prefix + "mHasAccuracy=" + mHasAccuracy + " mAccuracy=" + mAccuracy); - pw.println(prefix + "mExtras=" + mExtras); - } - /** * Constructs a new Location. By default, time, latitude, * longitude, and numSatellites are 0; hasAltitude, hasSpeed, and @@ -766,25 +756,46 @@ public class Location implements Parcelable { mExtras = (extras == null) ? null : new Bundle(extras); } - @Override public String toString() { - return "Location[mProvider=" + mProvider + - ",mTime=" + mTime + - ",mElapsedRealtimeNano=" + mElapsedRealtimeNano + - ",mLatitude=" + mLatitude + - ",mLongitude=" + mLongitude + - ",mHasAltitude=" + mHasAltitude + - ",mAltitude=" + mAltitude + - ",mHasSpeed=" + mHasSpeed + - ",mSpeed=" + mSpeed + - ",mHasBearing=" + mHasBearing + - ",mBearing=" + mBearing + - ",mHasAccuracy=" + mHasAccuracy + - ",mAccuracy=" + mAccuracy + - ",mExtras=" + mExtras + "]"; + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + s.append("Location["); + s.append(mProvider); + s.append(String.format(" %.6f,%.6f", mLatitude, mLongitude)); + if (mHasAccuracy) s.append(String.format(" acc=%.0f", mAccuracy)); + else s.append(" acc=???"); + if (mTime == 0) { + s.append(" t=?!?"); + } + if (mElapsedRealtimeNano == 0) { + s.append(" et=?!?"); + } else { + long age = SystemClock.elapsedRealtimeNano() - mElapsedRealtimeNano; + s.append(" age="); + TimeUtils.formatDuration(age / 1000000L, s); + } + if (mHasAltitude) s.append(" alt=").append(mAltitude); + if (mHasSpeed) s.append(" vel=").append(mSpeed); + if (mHasBearing) s.append(" bear=").append(mBearing); + + if (mExtras != null) { + s.append(" {").append(mExtras).append('}'); + } + s.append(']'); + return s.toString(); + } + + /** + * @deprecated Use {@link #toString} instead + */ + @Deprecated + public void dump(Printer pw, String prefix) { + pw.println(prefix + toString()); } public static final Parcelable.Creator<Location> CREATOR = new Parcelable.Creator<Location>() { + @Override public Location createFromParcel(Parcel in) { String provider = in.readString(); Location l = new Location(provider); @@ -804,15 +815,18 @@ public class Location implements Parcelable { return l; } + @Override public Location[] newArray(int size) { return new Location[size]; } }; + @Override public int describeContents() { return 0; } + @Override public void writeToParcel(Parcel parcel, int flags) { parcel.writeString(mProvider); parcel.writeLong(mTime); @@ -828,5 +842,5 @@ public class Location implements Parcelable { parcel.writeInt(mHasAccuracy ? 1 : 0); parcel.writeFloat(mAccuracy); parcel.writeBundle(mExtras); - } + } } diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 15a2928..083b900 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -25,15 +25,15 @@ import android.os.Looper; import android.os.RemoteException; import android.os.Handler; import android.os.Message; -import android.os.SystemClock; import android.util.Log; -import com.android.internal.location.DummyLocationProvider; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import com.android.internal.location.ProviderProperties; + /** * This class provides access to the system location services. These * services allow applications to obtain periodic updates of the @@ -71,7 +71,9 @@ public class LocationManager { * * Requires either of the permissions android.permission.ACCESS_COARSE_LOCATION * or android.permission.ACCESS_FINE_LOCATION. + * @deprecated use the {@link Criteria} class instead */ + @Deprecated public static final String NETWORK_PROVIDER = "network"; /** @@ -87,7 +89,9 @@ public class LocationManager { * <ul> * <li> satellites - the number of satellites used to derive the fix * </ul> + * @deprecated use the {@link Criteria} class instead */ + @Deprecated public static final String GPS_PROVIDER = "gps"; /** @@ -100,10 +104,22 @@ public class LocationManager { * * Requires the permission android.permission.ACCESS_FINE_LOCATION, although if the GPS * is not enabled this provider might only return coarse fixes. + * @deprecated use the {@link Criteria} class instead */ + @Deprecated public static final String PASSIVE_PROVIDER = "passive"; /** + * Name of the Fused location provider.<p> + * This provider combines inputs for all possible location sources + * to provide the best possible Location fix.<p> + * + * Requires the permission android.permission.ACCESS_FINE_LOCATION. + * @hide + */ + public static final String FUSED_PROVIDER = "fused"; + + /** * Key used for the Bundle extra holding a boolean indicating whether * a proximity alert is entering (true) or exiting (false).. */ @@ -112,13 +128,17 @@ public class LocationManager { /** * Key used for a Bundle extra holding an Integer status value * when a status change is broadcast using a PendingIntent. + * @deprecated use the {@link Criteria} class instead */ + @Deprecated public static final String KEY_STATUS_CHANGED = "status"; /** * Key used for a Bundle extra holding an Boolean status value * when a provider enabled/disabled event is broadcast using a PendingIntent. + * @deprecated use the {@link Criteria} class instead */ + @Deprecated public static final String KEY_PROVIDER_ENABLED = "providerEnabled"; /** @@ -141,7 +161,9 @@ public class LocationManager { /** * Broadcast intent action when the configured location providers * change. + * @deprecated use the {@link Criteria} class instead */ + @Deprecated public static final String PROVIDERS_CHANGED_ACTION = "android.location.PROVIDERS_CHANGED"; @@ -274,19 +296,8 @@ public class LocationManager { mContext = context; } - private LocationProvider createProvider(String name, Bundle info) { - DummyLocationProvider provider = - new DummyLocationProvider(name, mService); - provider.setRequiresNetwork(info.getBoolean("network")); - provider.setRequiresSatellite(info.getBoolean("satellite")); - provider.setRequiresCell(info.getBoolean("cell")); - provider.setHasMonetaryCost(info.getBoolean("cost")); - provider.setSupportsAltitude(info.getBoolean("altitude")); - provider.setSupportsSpeed(info.getBoolean("speed")); - provider.setSupportsBearing(info.getBoolean("bearing")); - provider.setPowerRequirement(info.getInt("power")); - provider.setAccuracy(info.getInt("accuracy")); - return provider; + private LocationProvider createProvider(String name, ProviderProperties properties) { + return new LocationProvider(name, properties); } /** @@ -295,15 +306,14 @@ public class LocationManager { * accessed by the calling activity or are currently disabled. * * @return list of Strings containing names of the providers + * @deprecated use the {@link Criteria} class instead */ + @Deprecated public List<String> getAllProviders() { - if (false) { - Log.d(TAG, "getAllProviders"); - } try { return mService.getAllProviders(); - } catch (RemoteException ex) { - Log.e(TAG, "getAllProviders: RemoteException", ex); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } return null; } @@ -315,12 +325,16 @@ public class LocationManager { * @param enabledOnly if true then only the providers which are currently * enabled are returned. * @return list of Strings containing names of the providers + * @deprecated The {@link LocationProvider} class is deprecated. So + * use the {@link Criteria} class to request location instead of + * enumerating providers. */ + @Deprecated public List<String> getProviders(boolean enabledOnly) { try { return mService.getProviders(null, enabledOnly); - } catch (RemoteException ex) { - Log.e(TAG, "getProviders: RemoteException", ex); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } return null; } @@ -332,22 +346,24 @@ public class LocationManager { * @param name the provider name * @return a LocationProvider, or null * - * @throws IllegalArgumentException if name is null + * @throws IllegalArgumentException if name is null or does not exisit * @throws SecurityException if the caller is not permitted to access the * given provider. + * @deprecated The {@link LocationProvider} class is deprecated. So + * use the {@link Criteria} class to request location instead of + * enumerating providers. */ + @Deprecated public LocationProvider getProvider(String name) { - if (name == null) { - throw new IllegalArgumentException("name==null"); - } + checkProvider(name); try { - Bundle info = mService.getProviderInfo(name); - if (info == null) { + ProviderProperties properties = mService.getProviderProperties(name); + if (properties == null) { return null; } - return createProvider(name, info); - } catch (RemoteException ex) { - Log.e(TAG, "getProvider: RemoteException", ex); + return createProvider(name, properties); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } return null; } @@ -361,15 +377,17 @@ public class LocationManager { * @param enabledOnly if true then only the providers which are currently * enabled are returned. * @return list of Strings containing names of the providers + * @deprecated The {@link LocationProvider} class is deprecated. So + * use the {@link Criteria} class to request location instead of + * enumerating providers. */ + @Deprecated public List<String> getProviders(Criteria criteria, boolean enabledOnly) { - if (criteria == null) { - throw new IllegalArgumentException("criteria==null"); - } + checkCriteria(criteria); try { return mService.getProviders(criteria, enabledOnly); - } catch (RemoteException ex) { - Log.e(TAG, "getProviders: RemoteException", ex); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } return null; } @@ -395,15 +413,15 @@ public class LocationManager { * @param criteria the criteria that need to be matched * @param enabledOnly if true then only a provider that is currently enabled is returned * @return name of the provider that best matches the requirements + * @deprecated using an explicit provider doesn't allow fused location */ + @Deprecated public String getBestProvider(Criteria criteria, boolean enabledOnly) { - if (criteria == null) { - throw new IllegalArgumentException("criteria==null"); - } + checkCriteria(criteria); try { return mService.getBestProvider(criteria, enabledOnly); - } catch (RemoteException ex) { - Log.e(TAG, "getBestProvider: RemoteException", ex); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } return null; } @@ -480,16 +498,17 @@ public class LocationManager { * @throws IllegalArgumentException if listener is null * @throws RuntimeException if the calling thread has no Looper * @throws SecurityException if no suitable permission is present for the provider. + * @deprecated use the {@link LocationRequest} class instead */ - public void requestLocationUpdates(String provider, - long minTime, float minDistance, LocationListener listener) { - if (provider == null) { - throw new IllegalArgumentException("provider==null"); - } - if (listener == null) { - throw new IllegalArgumentException("listener==null"); - } - _requestLocationUpdates(provider, null, minTime, minDistance, false, listener, null); + @Deprecated + public void requestLocationUpdates(String provider, long minTime, float minDistance, + LocationListener listener) { + checkProvider(provider); + checkListener(listener); + + LocationRequest request = LocationRequest.createFromDeprecatedProvider( + provider, minTime, minDistance, false); + requestLocationUpdates(request, listener, null, null); } /** @@ -564,17 +583,17 @@ public class LocationManager { * @throws IllegalArgumentException if provider is null or doesn't exist * @throws IllegalArgumentException if listener is null * @throws SecurityException if no suitable permission is present for the provider. + * @deprecated use the {@link LocationRequest} class instead */ - public void requestLocationUpdates(String provider, - long minTime, float minDistance, LocationListener listener, - Looper looper) { - if (provider == null) { - throw new IllegalArgumentException("provider==null"); - } - if (listener == null) { - throw new IllegalArgumentException("listener==null"); - } - _requestLocationUpdates(provider, null, minTime, minDistance, false, listener, looper); + @Deprecated + public void requestLocationUpdates(String provider, long minTime, float minDistance, + LocationListener listener, Looper looper) { + checkProvider(provider); + checkListener(listener); + + LocationRequest request = LocationRequest.createFromDeprecatedProvider( + provider, minTime, minDistance, false); + requestLocationUpdates(request, listener, looper, null); } /** @@ -639,39 +658,17 @@ public class LocationManager { * @throws IllegalArgumentException if criteria is null * @throws IllegalArgumentException if listener is null * @throws SecurityException if no suitable permission is present for the provider. + * @deprecated use the {@link LocationRequest} class instead */ - public void requestLocationUpdates(long minTime, float minDistance, - Criteria criteria, LocationListener listener, Looper looper) { - if (criteria == null) { - throw new IllegalArgumentException("criteria==null"); - } - if (listener == null) { - throw new IllegalArgumentException("listener==null"); - } - _requestLocationUpdates(null, criteria, minTime, minDistance, false, listener, looper); - } - - private void _requestLocationUpdates(String provider, Criteria criteria, long minTime, - float minDistance, boolean singleShot, LocationListener listener, Looper looper) { - if (minTime < 0L) { - minTime = 0L; - } - if (minDistance < 0.0f) { - minDistance = 0.0f; - } + @Deprecated + public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria, + LocationListener listener, Looper looper) { + checkCriteria(criteria); + checkListener(listener); - try { - synchronized (mListeners) { - ListenerTransport transport = mListeners.get(listener); - if (transport == null) { - transport = new ListenerTransport(listener, looper); - } - mListeners.put(listener, transport); - mService.requestLocationUpdates(provider, criteria, minTime, minDistance, singleShot, transport); - } - } catch (RemoteException ex) { - Log.e(TAG, "requestLocationUpdates: DeadObjectException", ex); - } + LocationRequest request = LocationRequest.createFromDeprecatedCriteria( + criteria, minTime, minDistance, false); + requestLocationUpdates(request, listener, looper, null); } /** @@ -749,16 +746,17 @@ public class LocationManager { * on this device * @throws IllegalArgumentException if intent is null * @throws SecurityException if no suitable permission is present for the provider. + * @deprecated use the {@link LocationRequest} class instead */ - public void requestLocationUpdates(String provider, - long minTime, float minDistance, PendingIntent intent) { - if (provider == null) { - throw new IllegalArgumentException("provider==null"); - } - if (intent == null) { - throw new IllegalArgumentException("intent==null"); - } - _requestLocationUpdates(provider, null, minTime, minDistance, false, intent); + @Deprecated + public void requestLocationUpdates(String provider, long minTime, float minDistance, + PendingIntent intent) { + checkProvider(provider); + checkPendingIntent(intent); + + LocationRequest request = LocationRequest.createFromDeprecatedProvider( + provider, minTime, minDistance, false); + requestLocationUpdates(request, null, null, intent); } /** @@ -825,32 +823,17 @@ public class LocationManager { * @throws IllegalArgumentException if criteria is null * @throws IllegalArgumentException if intent is null * @throws SecurityException if no suitable permission is present for the provider. + * @deprecated use the {@link LocationRequest} class instead */ + @Deprecated public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria, PendingIntent intent) { - if (criteria == null) { - throw new IllegalArgumentException("criteria==null"); - } - if (intent == null) { - throw new IllegalArgumentException("intent==null"); - } - _requestLocationUpdates(null, criteria, minTime, minDistance, false, intent); - } - - private void _requestLocationUpdates(String provider, Criteria criteria, - long minTime, float minDistance, boolean singleShot, PendingIntent intent) { - if (minTime < 0L) { - minTime = 0L; - } - if (minDistance < 0.0f) { - minDistance = 0.0f; - } + checkCriteria(criteria); + checkPendingIntent(intent); - try { - mService.requestLocationUpdatesPI(provider, criteria, minTime, minDistance, singleShot, intent); - } catch (RemoteException ex) { - Log.e(TAG, "requestLocationUpdates: RemoteException", ex); - } + LocationRequest request = LocationRequest.createFromDeprecatedCriteria( + criteria, minTime, minDistance, false); + requestLocationUpdates(request, null, null, intent); } /** @@ -879,15 +862,16 @@ public class LocationManager { * @throws IllegalArgumentException if provider is null or doesn't exist * @throws IllegalArgumentException if listener is null * @throws SecurityException if no suitable permission is present for the provider + * @deprecated use the {@link LocationRequest} class instead */ + @Deprecated public void requestSingleUpdate(String provider, LocationListener listener, Looper looper) { - if (provider == null) { - throw new IllegalArgumentException("provider==null"); - } - if (listener == null) { - throw new IllegalArgumentException("listener==null"); - } - _requestLocationUpdates(provider, null, 0L, 0.0f, true, listener, looper); + checkProvider(provider); + checkListener(listener); + + LocationRequest request = LocationRequest.createFromDeprecatedProvider( + provider, 0, 0, true); + requestLocationUpdates(request, listener, looper, null); } /** @@ -918,15 +902,16 @@ public class LocationManager { * @throws IllegalArgumentException if listener is null * @throws SecurityException if no suitable permission is present to access * the location services + * @deprecated use the {@link LocationRequest} class instead */ + @Deprecated public void requestSingleUpdate(Criteria criteria, LocationListener listener, Looper looper) { - if (criteria == null) { - throw new IllegalArgumentException("criteria==null"); - } - if (listener == null) { - throw new IllegalArgumentException("listener==null"); - } - _requestLocationUpdates(null, criteria, 0L, 0.0f, true, listener, looper); + checkCriteria(criteria); + checkListener(listener); + + LocationRequest request = LocationRequest.createFromDeprecatedCriteria( + criteria, 0, 0, true); + requestLocationUpdates(request, listener, looper, null); } /** @@ -951,15 +936,16 @@ public class LocationManager { * @throws IllegalArgumentException if provider is null or doesn't exist * @throws IllegalArgumentException if intent is null * @throws SecurityException if no suitable permission is present for the provider + * @deprecated use the {@link LocationRequest} class instead */ + @Deprecated public void requestSingleUpdate(String provider, PendingIntent intent) { - if (provider == null) { - throw new IllegalArgumentException("provider==null"); - } - if (intent == null) { - throw new IllegalArgumentException("intent==null"); - } - _requestLocationUpdates(provider, null, 0L, 0.0f, true, intent); + checkProvider(provider); + checkPendingIntent(intent); + + LocationRequest request = LocationRequest.createFromDeprecatedProvider( + provider, 0, 0, true); + requestLocationUpdates(request, null, null, intent); } /** @@ -986,15 +972,54 @@ public class LocationManager { * @throws IllegalArgumentException if provider is null or doesn't exist * @throws IllegalArgumentException if intent is null * @throws SecurityException if no suitable permission is present for the provider + * @deprecated use the {@link LocationRequest} class instead */ + @Deprecated public void requestSingleUpdate(Criteria criteria, PendingIntent intent) { - if (criteria == null) { - throw new IllegalArgumentException("criteria==null"); - } - if (intent == null) { - throw new IllegalArgumentException("intent==null"); + checkCriteria(criteria); + checkPendingIntent(intent); + + LocationRequest request = LocationRequest.createFromDeprecatedCriteria( + criteria, 0, 0, true); + requestLocationUpdates(request, null, null, intent); + } + + public void requestLocationUpdates(LocationRequest request, LocationListener listener, + Looper looper) { + checkListener(listener); + requestLocationUpdates(request, listener, looper, null); + } + + public void requestLocationUpdates(LocationRequest request, PendingIntent intent) { + checkPendingIntent(intent); + requestLocationUpdates(request, null, null, intent); + } + + private ListenerTransport wrapListener(LocationListener listener, Looper looper) { + if (listener == null) return null; + synchronized (mListeners) { + ListenerTransport transport = mListeners.get(listener); + if (transport == null) { + transport = new ListenerTransport(listener, looper); + } + mListeners.put(listener, transport); + return transport; } - _requestLocationUpdates(null, criteria, 0L, 0.0f, true, intent); + } + + private void requestLocationUpdates(LocationRequest request, LocationListener listener, + Looper looper, PendingIntent intent) { + + String packageName = mContext.getPackageName(); + + // wrap the listener class + ListenerTransport transport = wrapListener(listener, looper); + + try { + mService.requestLocationUpdates(request, transport, intent, packageName); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); + } } /** @@ -1006,19 +1031,19 @@ public class LocationManager { * @throws IllegalArgumentException if listener is null */ public void removeUpdates(LocationListener listener) { - if (listener == null) { - throw new IllegalArgumentException("listener==null"); - } - if (false) { - Log.d(TAG, "removeUpdates: listener = " + listener); + checkListener(listener); + String packageName = mContext.getPackageName(); + + ListenerTransport transport; + synchronized (mListeners) { + transport = mListeners.remove(listener); } + if (transport == null) return; + try { - ListenerTransport transport = mListeners.remove(listener); - if (transport != null) { - mService.removeUpdates(transport); - } - } catch (RemoteException ex) { - Log.e(TAG, "removeUpdates: DeadObjectException", ex); + mService.removeUpdates(transport, null, packageName); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } } @@ -1031,16 +1056,13 @@ public class LocationManager { * @throws IllegalArgumentException if intent is null */ public void removeUpdates(PendingIntent intent) { - if (intent == null) { - throw new IllegalArgumentException("intent==null"); - } - if (false) { - Log.d(TAG, "removeUpdates: intent = " + intent); - } + checkPendingIntent(intent); + String packageName = mContext.getPackageName(); + try { - mService.removeUpdatesPI(intent); - } catch (RemoteException ex) { - Log.e(TAG, "removeUpdates: RemoteException", ex); + mService.removeUpdates(null, intent, packageName); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } } @@ -1086,20 +1108,31 @@ public class LocationManager { * * @throws SecurityException if no permission exists for the required * providers. + * @deprecated use the {@link LocationRequest} class instead */ - public void addProximityAlert(double latitude, double longitude, - float radius, long expiration, PendingIntent intent) { - if (false) { - Log.d(TAG, "addProximityAlert: latitude = " + latitude + - ", longitude = " + longitude + ", radius = " + radius + - ", expiration = " + expiration + - ", intent = " + intent); + @Deprecated + public void addProximityAlert(double latitude, double longitude, float radius, long expiration, + PendingIntent intent) { + checkPendingIntent(intent); + if (expiration < 0) expiration = Long.MAX_VALUE; + + Geofence fence = Geofence.createCircle(latitude, longitude, radius); + LocationRequest request = new LocationRequest().setExpireIn(expiration); + try { + mService.requestGeofence(request, fence, intent, mContext.getPackageName()); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } + } + + public void requestGeofence(LocationRequest request, Geofence fence, PendingIntent intent) { + checkPendingIntent(intent); + checkGeofence(fence); + try { - mService.addProximityAlert(latitude, longitude, radius, expiration, intent, - mContext.getPackageName()); - } catch (RemoteException ex) { - Log.e(TAG, "addProximityAlert: RemoteException", ex); + mService.requestGeofence(request, fence, intent, mContext.getPackageName()); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } } @@ -1108,15 +1141,40 @@ public class LocationManager { * * @param intent the PendingIntent that no longer needs to be notified of * proximity alerts + * @deprecated use the {@link LocationRequest} class instead */ + @Deprecated public void removeProximityAlert(PendingIntent intent) { - if (false) { - Log.d(TAG, "removeProximityAlert: intent = " + intent); + checkPendingIntent(intent); + String packageName = mContext.getPackageName(); + + try { + mService.removeGeofence(null, intent, packageName); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } + } + + public void removeGeofence(Geofence fence, PendingIntent intent) { + checkPendingIntent(intent); + checkGeofence(fence); + String packageName = mContext.getPackageName(); + try { - mService.removeProximityAlert(intent); - } catch (RemoteException ex) { - Log.e(TAG, "removeProximityAlert: RemoteException", ex); + mService.removeGeofence(fence, intent, packageName); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); + } + } + + public void removeAllGeofences(PendingIntent intent) { + checkPendingIntent(intent); + String packageName = mContext.getPackageName(); + + try { + mService.removeGeofence(null, intent, packageName); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } } @@ -1130,19 +1188,30 @@ public class LocationManager { * * @throws SecurityException if no suitable permission is present for the provider. * @throws IllegalArgumentException if provider is null + * @deprecated use the {@link LocationRequest} class instead */ + @Deprecated public boolean isProviderEnabled(String provider) { - if (provider == null) { - throw new IllegalArgumentException("provider==null"); - } + checkProvider(provider); + try { return mService.isProviderEnabled(provider); - } catch (RemoteException ex) { - Log.e(TAG, "isProviderEnabled: RemoteException", ex); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); return false; } } + public Location getLastLocation(LocationRequest request) { + try { + return mService.getLastLocation(request); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); + return null; + } + } + + /** * Returns a Location indicating the data from the last known * location fix obtained from the given provider. This can be done @@ -1157,15 +1226,49 @@ public class LocationManager { * * @throws SecurityException if no suitable permission is present for the provider. * @throws IllegalArgumentException if provider is null or doesn't exist + * @deprecated use the {@link LocationRequest} class instead */ + @Deprecated public Location getLastKnownLocation(String provider) { - if (provider == null) { - throw new IllegalArgumentException("provider==null"); + checkProvider(provider); + + LocationRequest request = LocationRequest.createFromDeprecatedProvider( + provider, 0, 0, true); + + try { + return mService.getLastLocation(request); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); + return null; } + } + + /** + * Return the last know Location that satisfies the given + * criteria. This can be done without starting the provider. + * Note that this location could + * be out-of-date, for example if the device was turned off and + * moved to another location. + * + * <p> If no location is found that satisfies the criteria, null is returned + * + * @param criteria location criteria + * @return the last known location that satisfies criteria, or null + * + * @throws SecurityException if no suitable permission is present + * @throws IllegalArgumentException if criteria is null + * @deprecated use the {@link LocationRequest} class instead + */ + @Deprecated + public Location getLastKnownLocation(Criteria criteria) { + checkCriteria(criteria); + + LocationRequest request = LocationRequest.createFromDeprecatedCriteria( + criteria, 0, 0, true); try { - return mService.getLastKnownLocation(provider); - } catch (RemoteException ex) { - Log.e(TAG, "getLastKnowLocation: RemoteException", ex); + return mService.getLastLocation(request); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); return null; } } @@ -1190,16 +1293,23 @@ public class LocationManager { * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION * Settings.Secure.ALLOW_MOCK_LOCATION} system setting is not enabled * @throws IllegalArgumentException if a provider with the given name already exists + * @deprecated use the {@link LocationRequest} class instead */ + @Deprecated public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite, - boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude, - boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) { + boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude, + boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) { + ProviderProperties properties = new ProviderProperties(requiresNetwork, + requiresSatellite, requiresCell, hasMonetaryCost, supportsAltitude, supportsSpeed, + supportsBearing, powerRequirement, accuracy); + if (name.matches(LocationProvider.BAD_CHARS_REGEX)) { + throw new IllegalArgumentException("provider name contains illegal character: " + name); + } + try { - mService.addTestProvider(name, requiresNetwork, requiresSatellite, requiresCell, - hasMonetaryCost, supportsAltitude, supportsSpeed, supportsBearing, powerRequirement, - accuracy); - } catch (RemoteException ex) { - Log.e(TAG, "addTestProvider: RemoteException", ex); + mService.addTestProvider(name, properties); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } } @@ -1212,12 +1322,14 @@ public class LocationManager { * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled * @throws IllegalArgumentException if no provider with the given name exists + * @deprecated use the {@link LocationRequest} class instead */ + @Deprecated public void removeTestProvider(String provider) { try { mService.removeTestProvider(provider); - } catch (RemoteException ex) { - Log.e(TAG, "removeTestProvider: RemoteException", ex); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } } @@ -1236,23 +1348,27 @@ public class LocationManager { * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled * @throws IllegalArgumentException if no provider with the given name exists * @throws IllegalArgumentException if the location is incomplete + * @deprecated use the {@link LocationRequest} class instead */ + @Deprecated public void setTestProviderLocation(String provider, Location loc) { if (!loc.isComplete()) { + IllegalArgumentException e = new IllegalArgumentException( + "Incomplete location object, missing timestamp or accuracy? " + loc); if (mContext.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN) { - // for backwards compatibility, allow mock locations that are incomplete - Log.w(TAG, "Incomplete Location object", new Throwable()); + // just log on old platform (for backwards compatibility) + Log.w(TAG, e); loc.makeComplete(); } else { - throw new IllegalArgumentException( - "Location object not complete. Missing timestamps or accuracy?"); + // really throw it! + throw e; } } try { mService.setTestProviderLocation(provider, loc); - } catch (RemoteException ex) { - Log.e(TAG, "setTestProviderLocation: RemoteException", ex); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } } @@ -1265,12 +1381,14 @@ public class LocationManager { * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled * @throws IllegalArgumentException if no provider with the given name exists + * @deprecated use the {@link LocationRequest} class instead */ + @Deprecated public void clearTestProviderLocation(String provider) { try { mService.clearTestProviderLocation(provider); - } catch (RemoteException ex) { - Log.e(TAG, "clearTestProviderLocation: RemoteException", ex); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } } @@ -1285,12 +1403,14 @@ public class LocationManager { * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled * @throws IllegalArgumentException if no provider with the given name exists + * @deprecated use the {@link LocationRequest} class instead */ + @Deprecated public void setTestProviderEnabled(String provider, boolean enabled) { try { mService.setTestProviderEnabled(provider, enabled); - } catch (RemoteException ex) { - Log.e(TAG, "setTestProviderEnabled: RemoteException", ex); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } } @@ -1303,14 +1423,15 @@ public class LocationManager { * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled * @throws IllegalArgumentException if no provider with the given name exists + * @deprecated use the {@link LocationRequest} class instead */ + @Deprecated public void clearTestProviderEnabled(String provider) { try { mService.clearTestProviderEnabled(provider); - } catch (RemoteException ex) { - Log.e(TAG, "clearTestProviderEnabled: RemoteException", ex); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } - } /** @@ -1326,12 +1447,14 @@ public class LocationManager { * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled * @throws IllegalArgumentException if no provider with the given name exists + * @deprecated use the {@link LocationRequest} class instead */ + @Deprecated public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) { try { mService.setTestProviderStatus(provider, status, extras, updateTime); - } catch (RemoteException ex) { - Log.e(TAG, "setTestProviderStatus: RemoteException", ex); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } } @@ -1344,12 +1467,14 @@ public class LocationManager { * or the {@link android.provider.Settings.Secure#ALLOW_MOCK_LOCATION * Settings.Secure.ALLOW_MOCK_LOCATION}} system setting is not enabled * @throws IllegalArgumentException if no provider with the given name exists + * @deprecated use the {@link LocationRequest} class instead */ + @Deprecated public void clearTestProviderStatus(String provider) { try { mService.clearTestProviderStatus(provider); - } catch (RemoteException ex) { - Log.e(TAG, "clearTestProviderStatus: RemoteException", ex); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); } } @@ -1587,7 +1712,9 @@ public class LocationManager { * The provider may optionally fill the extras Bundle with results from the command. * * @return true if the command succeeds. + * @deprecated use the {@link LocationRequest} class instead */ + @Deprecated public boolean sendExtraCommand(String provider, String command, Bundle extras) { try { return mService.sendExtraCommand(provider, command, extras); @@ -1612,4 +1739,41 @@ public class LocationManager { } } + private static void checkProvider(String provider) { + if (provider == null) { + throw new IllegalArgumentException("invalid provider: " + provider); + } + } + + private static void checkCriteria(Criteria criteria) { + if (criteria == null) { + throw new IllegalArgumentException("invalid criteria: " + criteria); + } + } + private static void checkListener(LocationListener listener) { + if (listener == null) { + throw new IllegalArgumentException("invalid listener: " + listener); + } + } + + private void checkPendingIntent(PendingIntent intent) { + if (intent == null) { + throw new IllegalArgumentException("invalid pending intent: " + intent); + } + if (!intent.isTargetedToPackage()) { + IllegalArgumentException e = new IllegalArgumentException( + "pending intent msut be targeted to package"); + if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.JELLY_BEAN) { + throw e; + } else { + Log.w(TAG, e); + } + } + } + + private static void checkGeofence(Geofence fence) { + if (fence == null) { + throw new IllegalArgumentException("invalid geofence: " + fence); + } + } } diff --git a/location/java/android/location/LocationProvider.java b/location/java/android/location/LocationProvider.java index 8c16580..737e17f 100644 --- a/location/java/android/location/LocationProvider.java +++ b/location/java/android/location/LocationProvider.java @@ -16,8 +16,8 @@ package android.location; -import android.os.RemoteException; -import android.util.Log; + +import com.android.internal.location.ProviderProperties; /** * An abstract superclass for location providers. A location provider @@ -32,35 +32,40 @@ import android.util.Log; * characteristics or monetary costs to the user. The {@link * Criteria} class allows providers to be selected based on * user-specified criteria. + * + * @deprecated Use the {@link Criteria} class to request location instead of + * enumerating providers. */ -public abstract class LocationProvider { - private static final String TAG = "LocationProvider"; - // A regular expression matching characters that may not appear - // in the name of a LocationProvider. - static final String BAD_CHARS_REGEX = "[^a-zA-Z0-9]"; - - private final String mName; - private final ILocationManager mService; - +@Deprecated +public class LocationProvider { public static final int OUT_OF_SERVICE = 0; public static final int TEMPORARILY_UNAVAILABLE = 1; public static final int AVAILABLE = 2; /** + * A regular expression matching characters that may not appear + * in the name of a LocationProvider + * @hide + */ + public static final String BAD_CHARS_REGEX = "[^a-zA-Z0-9]"; + + private final String mName; + private final ProviderProperties mProperties; + + /** * Constructs a LocationProvider with the given name. Provider names must * consist only of the characters [a-zA-Z0-9]. * * @throws IllegalArgumentException if name contains an illegal character * - * {@hide} + * @hide */ - public LocationProvider(String name, ILocationManager service) { + public LocationProvider(String name, ProviderProperties properties) { if (name.matches(BAD_CHARS_REGEX)) { - throw new IllegalArgumentException("name " + name + - " contains an illegal character"); + throw new IllegalArgumentException("provider name contains illegal character: " + name); } mName = name; - mService = service; + mProperties = properties; } /** @@ -75,40 +80,81 @@ public abstract class LocationProvider { * false otherwise. */ public boolean meetsCriteria(Criteria criteria) { - try { - return mService.providerMeetsCriteria(mName, criteria); - } catch (RemoteException e) { - Log.e(TAG, "meetsCriteria: RemoteException", e); + return propertiesMeetCriteria(mName, mProperties, criteria); + } + + /** + * @hide + */ + public static boolean propertiesMeetCriteria(String name, ProviderProperties properties, + Criteria criteria) { + if (LocationManager.PASSIVE_PROVIDER.equals(name)) { + // passive provider never matches + return false; + } + if (properties == null) { + // unfortunately this can happen for provider in remote services + // that have not finished binding yet + return false; + } + + if (criteria.getAccuracy() != Criteria.NO_REQUIREMENT && + criteria.getAccuracy() < properties.mAccuracy) { return false; } + if (criteria.getPowerRequirement() != Criteria.NO_REQUIREMENT && + criteria.getPowerRequirement() < properties.mPowerRequirement) { + return false; + } + if (criteria.isAltitudeRequired() && !properties.mSupportsAltitude) { + return false; + } + if (criteria.isSpeedRequired() && !properties.mSupportsSpeed) { + return false; + } + if (criteria.isBearingRequired() && !properties.mSupportsBearing) { + return false; + } + if (!criteria.isCostAllowed() && properties.mHasMonetaryCost) { + return false; + } + return true; } /** * Returns true if the provider requires access to a * data network (e.g., the Internet), false otherwise. */ - public abstract boolean requiresNetwork(); + public boolean requiresNetwork() { + return mProperties.mRequiresNetwork; + } /** * Returns true if the provider requires access to a * satellite-based positioning system (e.g., GPS), false * otherwise. */ - public abstract boolean requiresSatellite(); + public boolean requiresSatellite() { + return mProperties.mRequiresSatellite; + } /** * Returns true if the provider requires access to an appropriate * cellular network (e.g., to make use of cell tower IDs), false * otherwise. */ - public abstract boolean requiresCell(); + public boolean requiresCell() { + return mProperties.mRequiresCell; + } /** * Returns true if the use of this provider may result in a * monetary charge to the user, false if use is free. It is up to * each provider to give accurate information. */ - public abstract boolean hasMonetaryCost(); + public boolean hasMonetaryCost() { + return mProperties.mHasMonetaryCost; + } /** * Returns true if the provider is able to provide altitude @@ -116,7 +162,9 @@ public abstract class LocationProvider { * under most circumstances but may occassionally not report it * should return true. */ - public abstract boolean supportsAltitude(); + public boolean supportsAltitude() { + return mProperties.mSupportsAltitude; + } /** * Returns true if the provider is able to provide speed @@ -124,7 +172,9 @@ public abstract class LocationProvider { * under most circumstances but may occassionally not report it * should return true. */ - public abstract boolean supportsSpeed(); + public boolean supportsSpeed() { + return mProperties.mSupportsSpeed; + } /** * Returns true if the provider is able to provide bearing @@ -132,7 +182,9 @@ public abstract class LocationProvider { * under most circumstances but may occassionally not report it * should return true. */ - public abstract boolean supportsBearing(); + public boolean supportsBearing() { + return mProperties.mSupportsBearing; + } /** * Returns the power requirement for this provider. @@ -140,7 +192,9 @@ public abstract class LocationProvider { * @return the power requirement for this provider, as one of the * constants Criteria.POWER_REQUIREMENT_*. */ - public abstract int getPowerRequirement(); + public int getPowerRequirement() { + return mProperties.mPowerRequirement; + } /** * Returns a constant describing horizontal accuracy of this provider. @@ -149,5 +203,7 @@ public abstract class LocationProvider { * location is only approximate then {@link Criteria#ACCURACY_COARSE} * is returned. */ - public abstract int getAccuracy(); + public int getAccuracy() { + return mProperties.mAccuracy; + } } diff --git a/location/java/android/location/LocationRequest.aidl b/location/java/android/location/LocationRequest.aidl new file mode 100644 index 0000000..b1a8647 --- /dev/null +++ b/location/java/android/location/LocationRequest.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2012, 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; + +parcelable LocationRequest; diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java new file mode 100644 index 0000000..3110196 --- /dev/null +++ b/location/java/android/location/LocationRequest.java @@ -0,0 +1,321 @@ +/* + * Copyright (C) 2012 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.Parcel; +import android.os.Parcelable; +import android.os.SystemClock; +import android.util.TimeUtils; + +public final class LocationRequest implements Parcelable { + // QOS control + public static final int ACCURACY_FINE = 100; // ~1 meter + public static final int ACCURACY_BLOCK = 102; // ~100 meters + public static final int ACCURACY_CITY = 104; // ~10 km + public static final int POWER_NONE = 200; + public static final int POWER_LOW = 201; + public static final int POWER_HIGH = 203; + + private int mQuality = POWER_LOW; + private long mFastestInterval = 6 * 1000; // 6 seconds + private long mInterval = 60 * 1000; // 1 minute + private long mExpireAt = Long.MAX_VALUE; // no expiry + private int mNumUpdates = Integer.MAX_VALUE; // no expiry + private float mSmallestDisplacement = 0.0f; // meters + + private String mProvider = null; // for deprecated API's that explicitly request a provider + + public static LocationRequest create() { + LocationRequest request = new LocationRequest(); + return request; + } + + /** @hide */ + public static LocationRequest createFromDeprecatedProvider(String provider, long minTime, + float minDistance, boolean singleShot) { + if (minTime < 0) minTime = 0; + if (minDistance < 0) minDistance = 0; + + int quality; + if (LocationManager.PASSIVE_PROVIDER.equals(provider)) { + quality = POWER_NONE; + } else if (LocationManager.GPS_PROVIDER.equals(provider)) { + quality = ACCURACY_FINE; + } else { + quality = POWER_LOW; + } + + LocationRequest request = new LocationRequest() + .setProvider(provider) + .setQuality(quality) + .setInterval(minTime) + .setFastestInterval(minTime) + .setSmallestDisplacement(minDistance); + if (singleShot) request.setNumUpdates(1); + return request; + } + + /** @hide */ + public static LocationRequest createFromDeprecatedCriteria(Criteria criteria, long minTime, + float minDistance, boolean singleShot) { + if (minTime < 0) minTime = 0; + if (minDistance < 0) minDistance = 0; + + int quality; + switch (criteria.getAccuracy()) { + case Criteria.ACCURACY_COARSE: + quality = ACCURACY_BLOCK; + break; + case Criteria.ACCURACY_FINE: + quality = ACCURACY_FINE; + break; + default: { + switch (criteria.getPowerRequirement()) { + case Criteria.POWER_HIGH: + quality = POWER_HIGH; + default: + quality = POWER_LOW; + } + } + } + + LocationRequest request = new LocationRequest() + .setQuality(quality) + .setInterval(minTime) + .setFastestInterval(minTime) + .setSmallestDisplacement(minDistance); + if (singleShot) request.setNumUpdates(1); + return request; + } + + /** @hide */ + public LocationRequest() { } + + public LocationRequest setQuality(int quality) { + checkQuality(quality); + mQuality = quality; + return this; + } + + public int getQuality() { + return mQuality; + } + + public LocationRequest setInterval(long millis) { + checkInterval(millis); + mInterval = millis; + return this; + } + + public long getInterval() { + return mInterval; + } + + public LocationRequest setFastestInterval(long millis) { + checkInterval(millis); + mFastestInterval = millis; + return this; + } + + public long getFastestInterval() { + return mFastestInterval; + } + + public LocationRequest setExpireIn(long millis) { + mExpireAt = millis + SystemClock.elapsedRealtime(); + if (mExpireAt < 0) mExpireAt = 0; + return this; + } + + public LocationRequest setExpireAt(long millis) { + mExpireAt = millis; + if (mExpireAt < 0) mExpireAt = 0; + return this; + } + + public long getExpireAt() { + return mExpireAt; + } + + public int getNumUpdates() { + return mNumUpdates; + } + + /** @hide */ + public void decrementNumUpdates() { + if (mNumUpdates != Integer.MAX_VALUE) { + mNumUpdates--; + } + if (mNumUpdates < 0) { + mNumUpdates = 0; + } + } + + public LocationRequest setNumUpdates(int numUpdates) { + if (numUpdates < 0) throw new IllegalArgumentException("invalid numUpdates: " + numUpdates); + mNumUpdates = numUpdates; + return this; + } + + /** @hide */ + public LocationRequest setProvider(String provider) { + checkProvider(provider); + mProvider = provider; + return this; + } + + /** @hide */ + public String getProvider() { + return mProvider; + } + + /** @hide */ + public LocationRequest setSmallestDisplacement(float meters) { + checkDisplacement(meters); + mSmallestDisplacement = meters; + return this; + } + + /** @hide */ + public float getSmallestDisplacement() { + return mSmallestDisplacement; + } + + /** @hide */ + public LocationRequest applyCoarsePermissionRestrictions() { + switch (mQuality) { + case ACCURACY_FINE: + mQuality = ACCURACY_BLOCK; + break; + } + // cap fastest interval to 6 seconds + if (mFastestInterval < 6 * 1000) mFastestInterval = 6 * 1000; + // cap requested interval to 1 minute + if (mInterval < 60 * 1000) mInterval = 60 * 1000; + return this; + } + + private static void checkInterval(long millis) { + if (millis < 0) { + throw new IllegalArgumentException("invalid interval: " + millis); + } + } + + private static void checkQuality(int quality) { + switch (quality) { + case ACCURACY_FINE: + case ACCURACY_BLOCK: + case ACCURACY_CITY: + case POWER_NONE: + case POWER_LOW: + case POWER_HIGH: + break; + default: + throw new IllegalArgumentException("invalid quality: " + quality); + } + } + + private static void checkDisplacement(float meters) { + if (meters < 0.0f) { + throw new IllegalArgumentException("invalid displacement: " + meters); + } + } + + private static void checkProvider(String name) { + if (name == null) { + throw new IllegalArgumentException("invalid provider: " + name); + } + } + + public static final Parcelable.Creator<LocationRequest> CREATOR = + new Parcelable.Creator<LocationRequest>() { + @Override + public LocationRequest createFromParcel(Parcel in) { + LocationRequest request = new LocationRequest(); + request.setQuality(in.readInt()); + request.setFastestInterval(in.readLong()); + request.setInterval(in.readLong()); + request.setExpireAt(in.readLong()); + request.setNumUpdates(in.readInt()); + request.setSmallestDisplacement(in.readFloat()); + String provider = in.readString(); + if (provider != null) request.setProvider(provider); + return request; + } + @Override + public LocationRequest[] newArray(int size) { + return new LocationRequest[size]; + } + }; + @Override + public int describeContents() { + return 0; + } + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeInt(mQuality); + parcel.writeLong(mFastestInterval); + parcel.writeLong(mInterval); + parcel.writeLong(mExpireAt); + parcel.writeInt(mNumUpdates); + parcel.writeFloat(mSmallestDisplacement); + parcel.writeString(mProvider); + } + + /** @hide */ + public static String qualityToString(int quality) { + switch (quality) { + case ACCURACY_FINE: + return "ACCURACY_FINE"; + case ACCURACY_BLOCK: + return "ACCURACY_BLOCK"; + case ACCURACY_CITY: + return "ACCURACY_CITY"; + case POWER_NONE: + return "POWER_NONE"; + case POWER_LOW: + return "POWER_LOW"; + case POWER_HIGH: + return "POWER_HIGH"; + default: + return "???"; + } + } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + s.append("Request[").append(qualityToString(mQuality)); + if (mProvider != null) s.append(' ').append(mProvider); + if (mQuality != POWER_NONE) { + s.append(" requested="); + TimeUtils.formatDuration(mInterval, s); + } + s.append(" fastest="); + TimeUtils.formatDuration(mFastestInterval, s); + if (mExpireAt != Long.MAX_VALUE) { + long expireIn = mExpireAt - SystemClock.elapsedRealtime(); + s.append(" expireIn="); + TimeUtils.formatDuration(expireIn, s); + } + if (mNumUpdates != Integer.MAX_VALUE){ + s.append(" num=").append(mNumUpdates); + } + s.append(']'); + return s.toString(); + } +} diff --git a/location/java/com/android/internal/location/DummyLocationProvider.java b/location/java/com/android/internal/location/DummyLocationProvider.java deleted file mode 100644 index 3122960..0000000 --- a/location/java/com/android/internal/location/DummyLocationProvider.java +++ /dev/null @@ -1,180 +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.location.ILocationManager; -import android.location.LocationProvider; - -/** - * A stub implementation of LocationProvider used by LocationManager. - * A DummyLocationProvider may be queried to determine the properties - * of the provider whcih it shadows, but does not actually provide location - * data. - * - * {@hide} - */ -public class DummyLocationProvider extends LocationProvider { - - private static final String TAG = "DummyLocationProvider"; - - String mName; - boolean mRequiresNetwork; - boolean mRequiresSatellite; - boolean mRequiresCell; - boolean mHasMonetaryCost; - boolean mSupportsAltitude; - boolean mSupportsSpeed; - boolean mSupportsBearing; - int mPowerRequirement; - int mAccuracy; - - public DummyLocationProvider(String name, ILocationManager service) { - super(name, service); - } - - public void setRequiresNetwork(boolean requiresNetwork) { - mRequiresNetwork = requiresNetwork; - } - - public void setRequiresSatellite(boolean requiresSatellite) { - mRequiresSatellite = requiresSatellite; - } - - public void setRequiresCell(boolean requiresCell) { - mRequiresCell = requiresCell; - } - - public void setHasMonetaryCost(boolean hasMonetaryCost) { - mHasMonetaryCost = hasMonetaryCost; - } - - public void setSupportsAltitude(boolean supportsAltitude) { - mSupportsAltitude = supportsAltitude; - } - - public void setSupportsSpeed(boolean supportsSpeed) { - mSupportsSpeed = supportsSpeed; - } - - public void setSupportsBearing(boolean supportsBearing) { - mSupportsBearing = supportsBearing; - } - - public void setPowerRequirement(int powerRequirement) { - mPowerRequirement = powerRequirement; - } - - public void setAccuracy(int accuracy) { - mAccuracy = accuracy; - } - - /** - * Returns true if the provider requires access to a - * data network (e.g., the Internet), false otherwise. - */ - @Override - public boolean requiresNetwork() { - return mRequiresNetwork; - } - - /** - * Returns true if the provider requires access to a - * satellite-based positioning system (e.g., GPS), false - * otherwise. - */ - @Override - public boolean requiresSatellite() { - return mRequiresSatellite; - } - - /** - * Returns true if the provider requires access to an appropriate - * cellular network (e.g., to make use of cell tower IDs), false - * otherwise. - */ - @Override - public boolean requiresCell() { - return mRequiresCell; - } - - /** - * Returns true if the use of this provider may result in a - * monetary charge to the user, false if use is free. It is up to - * each provider to give accurate information. - */ - @Override - public boolean hasMonetaryCost() { - return mHasMonetaryCost; - } - - /** - * Returns true if the provider is able to provide altitude - * information, false otherwise. A provider that reports altitude - * under most circumstances but may occassionally not report it - * should return true. - */ - @Override - public boolean supportsAltitude() { - return mSupportsAltitude; - } - - /** - * Returns true if the provider is able to provide speed - * information, false otherwise. A provider that reports speed - * under most circumstances but may occassionally not report it - * should return true. - */ - @Override - public boolean supportsSpeed() { - return mSupportsSpeed; - } - - /** - * Returns true if the provider is able to provide bearing - * information, false otherwise. A provider that reports bearing - * under most circumstances but may occassionally not report it - * should return true. - */ - @Override - public boolean supportsBearing() { - return mSupportsBearing; - } - - /** - * Returns the power requirement for this provider. - * - * @return the power requirement for this provider, as one of the - * constants Criteria.POWER_REQUIREMENT_*. - */ - @Override - public int getPowerRequirement() { - return mPowerRequirement; - } - - /** - * Returns a constant describing the horizontal accuracy returned - * by this provider. - * - * @return the horizontal accuracy for this provider, as one of the - * constants Criteria.ACCURACY_*. - */ - @Override - public int getAccuracy() { - return mAccuracy; - } -} - diff --git a/location/java/android/location/ILocationProvider.aidl b/location/java/com/android/internal/location/ILocationProvider.aidl index ecf6789..39c2d92 100644 --- a/location/java/android/location/ILocationProvider.aidl +++ b/location/java/com/android/internal/location/ILocationProvider.aidl @@ -14,40 +14,31 @@ * limitations under the License. */ -package android.location; +package com.android.internal.location; -import android.location.Criteria; import android.location.Location; import android.net.NetworkInfo; import android.os.Bundle; import android.os.WorkSource; +import com.android.internal.location.ProviderProperties; +import com.android.internal.location.ProviderRequest; + /** * Binder interface for services that implement location providers. - * - * {@hide} + * <p>Use {@link LocationProviderBase} as a helper to implement this + * interface. + * @hide */ interface ILocationProvider { - boolean requiresNetwork(); - boolean requiresSatellite(); - boolean requiresCell(); - boolean hasMonetaryCost(); - boolean supportsAltitude(); - boolean supportsSpeed(); - boolean supportsBearing(); - int getPowerRequirement(); - boolean meetsCriteria(in Criteria criteria); - int getAccuracy(); void enable(); void disable(); + + void setRequest(in ProviderRequest request, in WorkSource ws); + + // --- deprecated (but still supported) --- + ProviderProperties getProperties(); int getStatus(out Bundle extras); long getStatusUpdateTime(); - String getInternalState(); - void enableLocationTracking(boolean enable); - void setMinTime(long minTime, in WorkSource ws); - void updateNetworkState(int state, in NetworkInfo info); - void updateLocation(in Location location); boolean sendExtraCommand(String command, inout Bundle extras); - void addListener(int uid); - void removeListener(int uid); } diff --git a/location/java/com/android/internal/location/ProviderProperties.aidl b/location/java/com/android/internal/location/ProviderProperties.aidl new file mode 100644 index 0000000..b901444 --- /dev/null +++ b/location/java/com/android/internal/location/ProviderProperties.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2012, 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; + +parcelable ProviderProperties; diff --git a/location/java/com/android/internal/location/ProviderProperties.java b/location/java/com/android/internal/location/ProviderProperties.java new file mode 100644 index 0000000..08aed80 --- /dev/null +++ b/location/java/com/android/internal/location/ProviderProperties.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2012 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.os.Parcel; +import android.os.Parcelable; + +/** + * A Parcelable containing (legacy) location provider properties. + * This object is just used inside the framework and system services. + * @hide + */ +public final class ProviderProperties implements Parcelable { + /** + * True if provider requires access to a + * data network (e.g., the Internet), false otherwise. + */ + public final boolean mRequiresNetwork; + + /** + * True if the provider requires access to a + * satellite-based positioning system (e.g., GPS), false + * otherwise. + */ + public final boolean mRequiresSatellite; + + /** + * True if the provider requires access to an appropriate + * cellular network (e.g., to make use of cell tower IDs), false + * otherwise. + */ + public final boolean mRequiresCell; + + /** + * 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. Cell (network) usage + * is not considered monetary cost. + */ + public final boolean mHasMonetaryCost; + + /** + * True if the provider is able to provide altitude + * information, false otherwise. A provider that reports altitude + * under most circumstances but may occasionally not report it + * should return true. + */ + public final boolean mSupportsAltitude; + + /** + * True if the provider is able to provide speed + * information, false otherwise. A provider that reports speed + * under most circumstances but may occasionally not report it + * should return true. + */ + public final boolean mSupportsSpeed; + + /** + * True if the provider is able to provide bearing + * information, false otherwise. A provider that reports bearing + * under most circumstances but may occasionally not report it + * should return true. + */ + public final boolean mSupportsBearing; + + /** + * Power requirement for this provider. + * + * @return the power requirement for this provider, as one of the + * constants Criteria.POWER_*. + */ + public final int mPowerRequirement; + + /** + * Constant describing the horizontal accuracy returned + * by this provider. + * + * @return the horizontal accuracy for this provider, as one of the + * constants Criteria.ACCURACY_COARSE or Criteria.ACCURACY_FINE + */ + public final int mAccuracy; + + public ProviderProperties(boolean mRequiresNetwork, + boolean mRequiresSatellite, boolean mRequiresCell, boolean mHasMonetaryCost, + boolean mSupportsAltitude, boolean mSupportsSpeed, boolean mSupportsBearing, + int mPowerRequirement, int mAccuracy) { + this.mRequiresNetwork = mRequiresNetwork; + this.mRequiresSatellite = mRequiresSatellite; + this.mRequiresCell = mRequiresCell; + this.mHasMonetaryCost = mHasMonetaryCost; + this.mSupportsAltitude = mSupportsAltitude; + this.mSupportsSpeed = mSupportsSpeed; + this.mSupportsBearing = mSupportsBearing; + this.mPowerRequirement = mPowerRequirement; + this.mAccuracy = mAccuracy; + } + + public static final Parcelable.Creator<ProviderProperties> CREATOR = + new Parcelable.Creator<ProviderProperties>() { + @Override + public ProviderProperties createFromParcel(Parcel in) { + boolean requiresNetwork = in.readInt() == 1; + boolean requiresSatellite = in.readInt() == 1; + boolean requiresCell = in.readInt() == 1; + boolean hasMonetaryCost = in.readInt() == 1; + boolean supportsAltitude = in.readInt() == 1; + boolean supportsSpeed = in.readInt() == 1; + boolean supportsBearing = in.readInt() == 1; + int powerRequirement = in.readInt(); + int accuracy = in.readInt(); + return new ProviderProperties(requiresNetwork, requiresSatellite, + requiresCell, hasMonetaryCost, supportsAltitude, supportsSpeed, supportsBearing, + powerRequirement, accuracy); + } + @Override + public ProviderProperties[] newArray(int size) { + return new ProviderProperties[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeInt(mRequiresNetwork ? 1 : 0); + parcel.writeInt(mRequiresSatellite ? 1 : 0); + parcel.writeInt(mRequiresCell ? 1 : 0); + parcel.writeInt(mHasMonetaryCost ? 1 : 0); + parcel.writeInt(mSupportsAltitude ? 1 : 0); + parcel.writeInt(mSupportsSpeed ? 1 : 0); + parcel.writeInt(mSupportsSpeed ? 1 : 0); + parcel.writeInt(mPowerRequirement); + parcel.writeInt(mAccuracy); + } +} diff --git a/location/java/com/android/internal/location/ProviderRequest.aidl b/location/java/com/android/internal/location/ProviderRequest.aidl new file mode 100644 index 0000000..4e1ea95 --- /dev/null +++ b/location/java/com/android/internal/location/ProviderRequest.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2012 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; + +parcelable ProviderRequest; diff --git a/location/java/com/android/internal/location/ProviderRequest.java b/location/java/com/android/internal/location/ProviderRequest.java new file mode 100644 index 0000000..25c51f5 --- /dev/null +++ b/location/java/com/android/internal/location/ProviderRequest.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2012 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 java.util.ArrayList; +import java.util.List; + +import android.location.LocationRequest; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.TimeUtils; + +/** @hide */ +public final class ProviderRequest implements Parcelable { + /** Location reporting is requested (true) */ + public boolean reportLocation = false; + + /** The smallest requested interval */ + public long interval = Long.MAX_VALUE; + + /** + * A more detailed set of requests. + * <p>Location Providers can optionally use this to + * fine tune location updates, for example when there + * is a high power slow interval request and a + * low power fast interval request. + */ + public List<LocationRequest> locationRequests = null; + + public ProviderRequest() { + } + + public static final Parcelable.Creator<ProviderRequest> CREATOR = + new Parcelable.Creator<ProviderRequest>() { + @Override + public ProviderRequest createFromParcel(Parcel in) { + ProviderRequest request = new ProviderRequest(); + request.reportLocation = in.readInt() == 1; + request.interval = in.readLong(); + int count = in.readInt(); + request.locationRequests = new ArrayList<LocationRequest>(count); + for (int i = 0; i < count; i++) { + request.locationRequests.add(LocationRequest.CREATOR.createFromParcel(in)); + } + return request; + } + @Override + public ProviderRequest[] newArray(int size) { + return new ProviderRequest[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeInt(reportLocation ? 1 : 0); + parcel.writeLong(interval); + parcel.writeParcelableArray(locationRequests.toArray( + new LocationRequest[locationRequests.size()]), 0); + } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + s.append("ProviderRequest["); + if (reportLocation) { + s.append("ON"); + s.append(" interval="); + TimeUtils.formatDuration(interval, s); + } else { + s.append("OFF"); + } + s.append(']'); + return s.toString(); + } +} diff --git a/location/lib/Android.mk b/location/lib/Android.mk index a06478a..62f5677 100644 --- a/location/lib/Android.mk +++ b/location/lib/Android.mk @@ -23,7 +23,8 @@ LOCAL_MODULE:= com.android.location.provider LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := \ - $(call all-subdir-java-files) + $(call all-subdir-java-files) \ + $(call all-aidl-files-under, java) include $(BUILD_JAVA_LIBRARY) diff --git a/location/lib/java/com/android/location/provider/LocationProvider.java b/location/lib/java/com/android/location/provider/LocationProvider.java deleted file mode 100644 index 3714f40..0000000 --- a/location/lib/java/com/android/location/provider/LocationProvider.java +++ /dev/null @@ -1,358 +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 com.android.location.provider; - -import android.content.Context; -import android.net.NetworkInfo; -import android.location.Criteria; -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.os.WorkSource; -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 boolean meetsCriteria(Criteria criteria) { - return LocationProvider.this.onMeetsCriteria(criteria); - } - - 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 String getInternalState() { - return LocationProvider.this.onGetInternalState(); - } - - public void enableLocationTracking(boolean enable) { - LocationProvider.this.onEnableLocationTracking(enable); - } - - public void setMinTime(long minTime, WorkSource ws) { - LocationProvider.this.onSetMinTime(minTime, ws); - } - - 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, new WorkSource(uid)); - } - - public void removeListener(int uid) { - LocationProvider.this.onRemoveListener(uid, new WorkSource(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, false); - } 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 true if this provider meets the given criteria, - * false otherwise. - */ - public abstract boolean onMeetsCriteria(Criteria criteria); - - /** - * 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 android.location.LocationProvider#OUT_OF_SERVICE} is returned if the provider is - * out of service, and this is not expected to change in the near - * future; {@link android.location.LocationProvider#TEMPORARILY_UNAVAILABLE} is returned if - * the provider is temporarily unavailable but is expected to be - * available shortly; and {@link android.location.LocationProvider#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(); - - /** - * Returns debugging information about the location provider. - * - * @return string describing the internal state of the location provider, or null. - */ - public abstract String onGetInternalState(); - - /** - * 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. - * @param ws the source this work is coming from. - */ - public abstract void onSetMinTime(long minTime, WorkSource ws); - - /** - * Updates the network state for the given provider. This function must - * be overwritten if {@link android.location.LocationProvider#requiresNetwork} returns true. - * The state is {@link android.location.LocationProvider#TEMPORARILY_UNAVAILABLE} (disconnected) - * OR {@link android.location.LocationProvider#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. - * @param ws a WorkSource representation of the client. - */ - public abstract void onAddListener(int uid, WorkSource ws); - - /** - * Notifies the location provider when a client is no longer listening for locations. - * - * @param uid user ID of the client no longer listening. - * @param ws a WorkSource representation of the client. - */ - public abstract void onRemoveListener(int uid, WorkSource ws); -} diff --git a/location/lib/java/com/android/location/provider/LocationProviderBase.java b/location/lib/java/com/android/location/provider/LocationProviderBase.java new file mode 100644 index 0000000..53b0cae --- /dev/null +++ b/location/lib/java/com/android/location/provider/LocationProviderBase.java @@ -0,0 +1,184 @@ +/* + * 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.location.provider; + +import java.io.FileDescriptor; +import java.io.FileOutputStream; +import java.io.PrintWriter; + +import android.content.Context; +import android.location.ILocationManager; +import android.location.Location; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.WorkSource; +import android.util.Log; + +import com.android.internal.location.ILocationProvider; +import com.android.internal.location.ProviderProperties; +import com.android.internal.location.ProviderRequest; + + +/** + * Base class for location providers implemented as services. + * @hide + */ +public abstract class LocationProviderBase { + private final String TAG; + + protected final ILocationManager mLocationManager; + private final ProviderProperties mProperties; + private final IBinder mBinder; + + private final class Service extends ILocationProvider.Stub { + @Override + public void enable() { + onEnable(); + } + @Override + public void disable() { + onDisable(); + } + @Override + public void setRequest(ProviderRequest request, WorkSource ws) { + onSetRequest(new ProviderRequestUnbundled(request), ws); + } + @Override + public ProviderProperties getProperties() { + return mProperties; + } + @Override + public int getStatus(Bundle extras) { + return onGetStatus(extras); + } + @Override + public long getStatusUpdateTime() { + return onGetStatusUpdateTime(); + } + @Override + public boolean sendExtraCommand(String command, Bundle extras) { + return onSendExtraCommand(command, extras); + } + @Override + public void dump(FileDescriptor fd, String[] args) { + PrintWriter pw = new PrintWriter(new FileOutputStream(fd)); + onDump(fd, pw, args); + pw.flush(); + } + } + + public LocationProviderBase(String tag, ProviderPropertiesUnbundled properties) { + TAG = tag; + IBinder b = ServiceManager.getService(Context.LOCATION_SERVICE); + mLocationManager = ILocationManager.Stub.asInterface(b); + mProperties = properties.getProviderProperties(); + mBinder = new Service(); + } + + public IBinder getBinder() { + return mBinder; + } + + /** + * Used by the location provider to report new locations. + * + * @param location new Location to report + * + * Requires the android.permission.INSTALL_LOCATION_PROVIDER permission. + */ + public final void reportLocation(Location location) { + try { + mLocationManager.reportLocation(location, false); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException", e); + } catch (Exception e) { + // never crash provider, might be running in a system process + Log.e(TAG, "Exception", e); + } + } + + /** + * Enable the location provider. + * <p>The provider may initialize resources, but does + * not yet need to report locations. + */ + public abstract void onEnable(); + + /** + * Disable the location provider. + * <p>The provider must release resources, and stop + * performing work. It may no longer report locations. + */ + public abstract void onDisable(); + + /** + * Set the {@link ProviderRequest} requirements for this provider. + * <p>Each call to this method overrides all previous requests. + * <p>This method might trigger the provider to start returning + * locations, or to stop returning locations, depending on the + * parameters in the request. + */ + public abstract void onSetRequest(ProviderRequestUnbundled request, WorkSource source); + + /** + * Dump debug information. + */ + public void onDump(FileDescriptor fd, PrintWriter pw, String[] args) { + } + + /** + * Returns a information on the status of this provider. + * <p>{@link android.location.LocationProvider#OUT_OF_SERVICE} is returned if the provider is + * out of service, and this is not expected to change in the near + * future; {@link android.location.LocationProvider#TEMPORARILY_UNAVAILABLE} is returned if + * the provider is temporarily unavailable but is expected to be + * available shortly; and {@link android.location.LocationProvider#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(); + + /** + * 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 onSendExtraCommand(String command, Bundle extras) { + // default implementation + return false; + } +} diff --git a/location/lib/java/com/android/location/provider/ProviderPropertiesUnbundled.java b/location/lib/java/com/android/location/provider/ProviderPropertiesUnbundled.java new file mode 100644 index 0000000..c8bdda4 --- /dev/null +++ b/location/lib/java/com/android/location/provider/ProviderPropertiesUnbundled.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2012 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.location.provider; + +import com.android.internal.location.ProviderProperties; + +/** + * This class is a public API for unbundled providers, + * that hides the (hidden framework) ProviderProperties. + * <p>Do _not_ remove public methods on this class. + */ +public final class ProviderPropertiesUnbundled { + private final ProviderProperties mProperties; + + public static ProviderPropertiesUnbundled create(boolean requiresNetwork, + boolean requiresSatellite, boolean requiresCell, boolean hasMonetaryCost, + boolean supportsAltitude, boolean supportsSpeed, boolean supportsBearing, + int powerRequirement, int accuracy) { + return new ProviderPropertiesUnbundled(new ProviderProperties(requiresNetwork, + requiresSatellite, requiresCell, hasMonetaryCost, supportsAltitude, supportsSpeed, + supportsBearing, powerRequirement, accuracy)); + } + + private ProviderPropertiesUnbundled(ProviderProperties properties) { + mProperties = properties; + } + + public ProviderProperties getProviderProperties() { + return mProperties; + } + + @Override + public String toString() { + return mProperties.toString(); + } +} diff --git a/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java b/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java new file mode 100644 index 0000000..7487a56 --- /dev/null +++ b/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2012 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.location.provider; + +import java.util.List; + +import android.location.LocationRequest; + +import com.android.internal.location.ProviderRequest; + +/** + * This class is a public API for unbundled providers, + * that hides the (hidden framework) ProviderRequest. + * <p>Do _not_ remove public methods on this class. + */ +public final class ProviderRequestUnbundled { + private final ProviderRequest mRequest; + + public ProviderRequestUnbundled(ProviderRequest request) { + mRequest = request; + } + + public boolean getReportLocation() { + return mRequest.reportLocation; + } + + public long getInterval() { + return mRequest.interval; + } + + public List<LocationRequest> getLocationRequests() { + return mRequest.locationRequests; + } + + @Override + public String toString() { + return mRequest.toString(); + } +} |