diff options
Diffstat (limited to 'core/java/android/hardware/location')
10 files changed, 321 insertions, 67 deletions
diff --git a/core/java/android/hardware/location/GeofenceHardware.java b/core/java/android/hardware/location/GeofenceHardware.java index 2d7b7e1..2d82cba 100644 --- a/core/java/android/hardware/location/GeofenceHardware.java +++ b/core/java/android/hardware/location/GeofenceHardware.java @@ -16,6 +16,7 @@ package android.hardware.location; import android.location.Location; +import android.os.Build; import android.os.RemoteException; import java.lang.ref.WeakReference; @@ -60,19 +61,19 @@ public final class GeofenceHardware { public static final int MONITORING_TYPE_FUSED_HARDWARE = 1; /** - * Constant to indiciate that the monitoring system is currently + * Constant to indicate that the monitoring system is currently * available for monitoring geofences. */ public static final int MONITOR_CURRENTLY_AVAILABLE = 0; /** - * Constant to indiciate that the monitoring system is currently + * Constant to indicate that the monitoring system is currently * unavailable for monitoring geofences. */ public static final int MONITOR_CURRENTLY_UNAVAILABLE = 1; /** - * Constant to indiciate that the monitoring system is unsupported + * Constant to indicate that the monitoring system is unsupported * for hardware geofence monitoring. */ public static final int MONITOR_UNSUPPORTED = 2; @@ -129,6 +130,33 @@ public final class GeofenceHardware { */ public static final int GEOFENCE_ERROR_INSUFFICIENT_MEMORY = 6; + // the following values must match the definitions in fused_location.h + + /** + * The constant used to indicate that the monitoring system supports GNSS. + */ + public static final int SOURCE_TECHNOLOGY_GNSS = (1<<0); + + /** + * The constant used to indicate that the monitoring system supports WiFi. + */ + public static final int SOURCE_TECHNOLOGY_WIFI = (1<<1); + + /** + * The constant used to indicate that the monitoring system supports Sensors. + */ + public static final int SOURCE_TECHNOLOGY_SENSORS = (1<<2); + + /** + * The constant used to indicate that the monitoring system supports Cell. + */ + public static final int SOURCE_TECHNOLOGY_CELL = (1<<3); + + /** + * The constant used to indicate that the monitoring system supports Bluetooth. + */ + public static final int SOURCE_TECHNOLOGY_BLUETOOTH = (1<<4); + private HashMap<GeofenceHardwareCallback, GeofenceHardwareCallbackWrapper> mCallbacks = new HashMap<GeofenceHardwareCallback, GeofenceHardwareCallbackWrapper>(); private HashMap<GeofenceHardwareMonitorCallback, GeofenceHardwareMonitorCallbackWrapper> @@ -238,13 +266,9 @@ public final class GeofenceHardware { geofenceRequest, GeofenceHardwareCallback callback) { try { if (geofenceRequest.getType() == GeofenceHardwareRequest.GEOFENCE_TYPE_CIRCLE) { - return mService.addCircularFence(geofenceId, monitoringType, - geofenceRequest.getLatitude(), - geofenceRequest.getLongitude(), geofenceRequest.getRadius(), - geofenceRequest.getLastTransition(), - geofenceRequest.getMonitorTransitions(), - geofenceRequest.getNotificationResponsiveness(), - geofenceRequest.getUnknownTimer(), + return mService.addCircularFence( + monitoringType, + new GeofenceHardwareRequestParcelable(geofenceId, geofenceRequest), getCallbackWrapper(callback)); } else { throw new IllegalArgumentException("Geofence Request type not supported"); @@ -452,10 +476,21 @@ public final class GeofenceHardware { mCallback = new WeakReference<GeofenceHardwareMonitorCallback>(c); } - public void onMonitoringSystemChange(int monitoringType, boolean available, - Location location) { + public void onMonitoringSystemChange(GeofenceHardwareMonitorEvent event) { GeofenceHardwareMonitorCallback c = mCallback.get(); - if (c != null) c.onMonitoringSystemChange(monitoringType, available, location); + if (c == null) return; + + // report the legacy event first, so older clients are not broken + c.onMonitoringSystemChange( + event.getMonitoringType(), + event.getMonitoringStatus() == GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE, + event.getLocation()); + + // and only call the updated callback on on L and above, this complies with the + // documentation of GeofenceHardwareMonitorCallback + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.L) { + c.onMonitoringSystemChange(event); + } } } diff --git a/core/java/android/hardware/location/GeofenceHardwareImpl.java b/core/java/android/hardware/location/GeofenceHardwareImpl.java index 6b61690..6734878 100644 --- a/core/java/android/hardware/location/GeofenceHardwareImpl.java +++ b/core/java/android/hardware/location/GeofenceHardwareImpl.java @@ -210,18 +210,20 @@ public final class GeofenceHardwareImpl { } } - public boolean addCircularFence(int geofenceId, int monitoringType, double latitude, - double longitude, double radius, int lastTransition,int monitorTransitions, - int notificationResponsivenes, int unknownTimer, IGeofenceHardwareCallback callback) { + public boolean addCircularFence( + int monitoringType, + GeofenceHardwareRequestParcelable request, + IGeofenceHardwareCallback callback) { + int geofenceId = request.getId(); + // This API is not thread safe. Operations on the same geofence need to be serialized // by upper layers if (DEBUG) { - Log.d(TAG, "addCircularFence: GeofenceId: " + geofenceId + " Latitude: " + latitude + - " Longitude: " + longitude + " Radius: " + radius + " LastTransition: " - + lastTransition + " MonitorTransition: " + monitorTransitions + - " NotificationResponsiveness: " + notificationResponsivenes + - " UnKnown Timer: " + unknownTimer + " MonitoringType: " + monitoringType); - + String message = String.format( + "addCircularFence: monitoringType=%d, %s", + monitoringType, + request); + Log.d(TAG, message); } boolean result; @@ -237,9 +239,15 @@ public final class GeofenceHardwareImpl { case GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE: if (mGpsService == null) return false; try { - result = mGpsService.addCircularHardwareGeofence(geofenceId, latitude, - longitude, radius, lastTransition, monitorTransitions, - notificationResponsivenes, unknownTimer); + result = mGpsService.addCircularHardwareGeofence( + request.getId(), + request.getLatitude(), + request.getLongitude(), + request.getRadius(), + request.getLastTransition(), + request.getMonitorTransitions(), + request.getNotificationResponsiveness(), + request.getUnknownTimer()); } catch (RemoteException e) { Log.e(TAG, "AddGeofence: Remote Exception calling LocationManagerService"); result = false; @@ -249,20 +257,9 @@ public final class GeofenceHardwareImpl { if(mFusedService == null) { return false; } - GeofenceHardwareRequest request = GeofenceHardwareRequest.createCircularGeofence( - latitude, - longitude, - radius); - request.setUnknownTimer(unknownTimer); - request.setNotificationResponsiveness(notificationResponsivenes); - request.setMonitorTransitions(monitorTransitions); - request.setLastTransition(lastTransition); - - GeofenceHardwareRequestParcelable parcelableRequest = - new GeofenceHardwareRequestParcelable(geofenceId, request); try { mFusedService.addGeofences( - new GeofenceHardwareRequestParcelable[] { parcelableRequest }); + new GeofenceHardwareRequestParcelable[] { request }); result = true; } catch(RemoteException e) { Log.e(TAG, "AddGeofence: RemoteException calling LocationManagerService"); @@ -471,12 +468,14 @@ public final class GeofenceHardwareImpl { int monitoringStatus, Location location, int source) { - // TODO: use the source if needed in the future setMonitorAvailability(monitoringType, monitoringStatus); acquireWakeLock(); - Message message = mCallbacksHandler.obtainMessage(GEOFENCE_STATUS, location); - message.arg1 = monitoringStatus; - message.arg2 = monitoringType; + GeofenceHardwareMonitorEvent event = new GeofenceHardwareMonitorEvent( + monitoringType, + monitoringStatus, + source, + location); + Message message = mCallbacksHandler.obtainMessage(GEOFENCE_STATUS, event); message.sendToTarget(); } @@ -644,20 +643,17 @@ public final class GeofenceHardwareImpl { switch (msg.what) { case GEOFENCE_STATUS: - Location location = (Location) msg.obj; - int val = msg.arg1; - monitoringType = msg.arg2; - boolean available; - available = (val == GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE ? - true : false); - callbackList = mCallbacks[monitoringType]; + GeofenceHardwareMonitorEvent event = (GeofenceHardwareMonitorEvent) msg.obj; + callbackList = mCallbacks[event.getMonitoringType()]; if (callbackList != null) { - if (DEBUG) Log.d(TAG, "MonitoringSystemChangeCallback: GPS : " + available); + if (DEBUG) Log.d(TAG, "MonitoringSystemChangeCallback: " + event); - for (IGeofenceHardwareMonitorCallback c: callbackList) { + for (IGeofenceHardwareMonitorCallback c : callbackList) { try { - c.onMonitoringSystemChange(monitoringType, available, location); - } catch (RemoteException e) {} + c.onMonitoringSystemChange(event); + } catch (RemoteException e) { + Log.d(TAG, "Error reporting onMonitoringSystemChange.", e); + } } } releaseWakeLock(); diff --git a/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java b/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java index b8e927e..f927027 100644 --- a/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java +++ b/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java @@ -19,19 +19,39 @@ package android.hardware.location; import android.location.Location; /** - * The callback class associated with the status change of hardware montiors + * The callback class associated with the status change of hardware monitors * in {@link GeofenceHardware} */ public abstract class GeofenceHardwareMonitorCallback { /** * The callback called when the state of a monitoring system changes. * {@link GeofenceHardware#MONITORING_TYPE_GPS_HARDWARE} is an example of a - * monitoring system + * monitoring system. + * + * @deprecated use {@link #onMonitoringSystemChange(GeofenceHardwareMonitorEvent)} instead. + * NOTE: this API is will remain to be called on Android API 21 and above for backwards + * compatibility. But clients must stop implementing it when updating their code. * * @param monitoringType The type of the monitoring system. - * @param available Indicates whether the system is currenty available or not. + * @param available Indicates whether the system is currently available or not. * @param location The last known location according to the monitoring system. */ + @Deprecated public void onMonitoringSystemChange(int monitoringType, boolean available, Location location) { } + + /** + * The callback called when the sate of a monitoring system changes. + * {@link GeofenceHardware#MONITORING_TYPE_GPS_HARDWARE} is an example of a monitoring system. + * {@link GeofenceHardware#MONITOR_CURRENTLY_AVAILABLE} is an example of a monitoring status. + * {@link GeofenceHardware#SOURCE_TECHNOLOGY_GNSS} is an example of a source. + * + * This callback must be used instead of + * {@link #onMonitoringSystemChange(int, boolean, android.location.Location)}. + * + * NOTE: this API is only called on Android API 21 and above. + * + * @param event An object representing the monitoring system change event. + */ + public void onMonitoringSystemChange(GeofenceHardwareMonitorEvent event) {} } diff --git a/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.aidl b/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.aidl new file mode 100644 index 0000000..008953e --- /dev/null +++ b/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2014 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.hardware.location; + +parcelable GeofenceHardwareMonitorEvent;
\ No newline at end of file diff --git a/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java b/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java new file mode 100644 index 0000000..9c460d2 --- /dev/null +++ b/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2014 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.hardware.location; + +import android.location.Location; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * A class that represents an event for each change in the state of a monitoring system. + */ +public class GeofenceHardwareMonitorEvent implements Parcelable { + private final int mMonitoringType; + private final int mMonitoringStatus; + private final int mSourceTechnologies; + private final Location mLocation; + + public GeofenceHardwareMonitorEvent( + int monitoringType, + int monitoringStatus, + int sourceTechnologies, + Location location) { + mMonitoringType = monitoringType; + mMonitoringStatus = monitoringStatus; + mSourceTechnologies = sourceTechnologies; + mLocation = location; + } + + /** + * Returns the type of the monitoring system that has a change on its state. + */ + public int getMonitoringType() { + return mMonitoringType; + } + + /** + * Returns the new status associated with the monitoring system. + */ + public int getMonitoringStatus() { + return mMonitoringStatus; + } + + /** + * Returns the source technologies that the status is associated to. + */ + public int getSourceTechnologies() { + return mSourceTechnologies; + } + + /** + * Returns the last known location according to the monitoring system. + */ + public Location getLocation() { + return mLocation; + } + + public static final Creator<GeofenceHardwareMonitorEvent> CREATOR = + new Creator<GeofenceHardwareMonitorEvent>() { + @Override + public GeofenceHardwareMonitorEvent createFromParcel(Parcel source) { + ClassLoader classLoader = GeofenceHardwareMonitorEvent.class.getClassLoader(); + int monitoringType = source.readInt(); + int monitoringStatus = source.readInt(); + int sourceTechnologies = source.readInt(); + Location location = source.readParcelable(classLoader); + + return new GeofenceHardwareMonitorEvent( + monitoringType, + monitoringStatus, + sourceTechnologies, + location); + } + + @Override + public GeofenceHardwareMonitorEvent[] newArray(int size) { + return new GeofenceHardwareMonitorEvent[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel parcel, int flags) { + parcel.writeInt(mMonitoringType); + parcel.writeInt(mMonitoringStatus); + parcel.writeInt(mSourceTechnologies); + parcel.writeParcelable(mLocation, flags); + } + + @Override + public String toString() { + return String.format( + "GeofenceHardwareMonitorEvent: type=%d, status=%d, sources=%d, location=%s", + mMonitoringType, + mMonitoringStatus, + mSourceTechnologies, + mLocation); + } +} diff --git a/core/java/android/hardware/location/GeofenceHardwareRequest.java b/core/java/android/hardware/location/GeofenceHardwareRequest.java index 796d7f8..887c4ad 100644 --- a/core/java/android/hardware/location/GeofenceHardwareRequest.java +++ b/core/java/android/hardware/location/GeofenceHardwareRequest.java @@ -33,6 +33,7 @@ public final class GeofenceHardwareRequest { private int mMonitorTransitions = GeofenceHardware.GEOFENCE_UNCERTAIN | GeofenceHardware.GEOFENCE_ENTERED | GeofenceHardware.GEOFENCE_EXITED; private int mNotificationResponsiveness = 5000; // 5 secs + private int mSourceTechnologies = GeofenceHardware.SOURCE_TECHNOLOGY_GNSS; private void setCircularGeofence(double latitude, double longitude, double radius) { mLatitude = latitude; @@ -102,6 +103,28 @@ public final class GeofenceHardwareRequest { } /** + * Set the source technologies to use while tracking the geofence. + * The value is the bit-wise of one or several source fields defined in + * {@link GeofenceHardware}. + * + * @param sourceTechnologies The set of source technologies to use. + */ + public void setSourceTechnologies(int sourceTechnologies) { + int sourceTechnologiesAll = GeofenceHardware.SOURCE_TECHNOLOGY_GNSS + | GeofenceHardware.SOURCE_TECHNOLOGY_WIFI + | GeofenceHardware.SOURCE_TECHNOLOGY_SENSORS + | GeofenceHardware.SOURCE_TECHNOLOGY_CELL + | GeofenceHardware.SOURCE_TECHNOLOGY_BLUETOOTH; + + int sanitizedSourceTechnologies = (sourceTechnologies & sourceTechnologiesAll); + if (sanitizedSourceTechnologies == 0) { + throw new IllegalArgumentException("At least one valid source technology must be set."); + } + + mSourceTechnologies = sanitizedSourceTechnologies; + } + + /** * Returns the latitude of this geofence. */ public double getLatitude() { @@ -150,6 +173,13 @@ public final class GeofenceHardwareRequest { return mLastTransition; } + /** + * Returns the source technologies to track this geofence. + */ + public int getSourceTechnologies() { + return mSourceTechnologies; + } + int getType() { return mType; } diff --git a/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java b/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java index 40e7fc4..d3311f5 100644 --- a/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java +++ b/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java @@ -98,9 +98,43 @@ public final class GeofenceHardwareRequestParcelable implements Parcelable { } /** + * Returns the source technologies to track this geofence. + */ + int getSourceTechnologies() { + return mRequest.getSourceTechnologies(); + } + + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("id="); + builder.append(mId); + builder.append(", type="); + builder.append(mRequest.getType()); + builder.append(", latitude="); + builder.append(mRequest.getLatitude()); + builder.append(", longitude="); + builder.append(mRequest.getLongitude()); + builder.append(", radius="); + builder.append(mRequest.getRadius()); + builder.append(", lastTransition="); + builder.append(mRequest.getLastTransition()); + builder.append(", unknownTimer="); + builder.append(mRequest.getUnknownTimer()); + builder.append(", monitorTransitions="); + builder.append(mRequest.getMonitorTransitions()); + builder.append(", notificationResponsiveness="); + builder.append(mRequest.getNotificationResponsiveness()); + builder.append(", sourceTechnologies="); + builder.append(mRequest.getSourceTechnologies()); + return builder.toString(); + } + + /** * Method definitions to support Parcelable operations. */ - public static final Parcelable.Creator<GeofenceHardwareRequestParcelable> CREATOR = + public static final Parcelable.Creator<GeofenceHardwareRequestParcelable> CREATOR = new Parcelable.Creator<GeofenceHardwareRequestParcelable>() { @Override public GeofenceHardwareRequestParcelable createFromParcel(Parcel parcel) { @@ -120,7 +154,8 @@ public final class GeofenceHardwareRequestParcelable implements Parcelable { request.setMonitorTransitions(parcel.readInt()); request.setUnknownTimer(parcel.readInt()); request.setNotificationResponsiveness(parcel.readInt()); - + request.setSourceTechnologies(parcel.readInt()); + int id = parcel.readInt(); return new GeofenceHardwareRequestParcelable(id, request); } @@ -146,6 +181,7 @@ public final class GeofenceHardwareRequestParcelable implements Parcelable { parcel.writeInt(getMonitorTransitions()); parcel.writeInt(getUnknownTimer()); parcel.writeInt(getNotificationResponsiveness()); + parcel.writeInt(getSourceTechnologies()); parcel.writeInt(getId()); } } diff --git a/core/java/android/hardware/location/GeofenceHardwareService.java b/core/java/android/hardware/location/GeofenceHardwareService.java index fb238bd..4816c5f 100644 --- a/core/java/android/hardware/location/GeofenceHardwareService.java +++ b/core/java/android/hardware/location/GeofenceHardwareService.java @@ -86,15 +86,14 @@ public class GeofenceHardwareService extends Service { return mGeofenceHardwareImpl.getStatusOfMonitoringType(monitoringType); } - public boolean addCircularFence(int id, int monitoringType, double lat, double longitude, - double radius, int lastTransition, int monitorTransitions, int - notificationResponsiveness, int unknownTimer, IGeofenceHardwareCallback callback) { + public boolean addCircularFence( + int monitoringType, + GeofenceHardwareRequestParcelable request, + IGeofenceHardwareCallback callback) { mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, "Location Hardware permission not granted to access hardware geofence"); checkPermission(Binder.getCallingPid(), Binder.getCallingUid(), monitoringType); - return mGeofenceHardwareImpl.addCircularFence(id, monitoringType, lat, longitude, - radius, lastTransition, monitorTransitions, notificationResponsiveness, - unknownTimer, callback); + return mGeofenceHardwareImpl.addCircularFence(monitoringType, request, callback); } public boolean removeGeofence(int id, int monitoringType) { diff --git a/core/java/android/hardware/location/IGeofenceHardware.aidl b/core/java/android/hardware/location/IGeofenceHardware.aidl index 8900166..0e840c4 100644 --- a/core/java/android/hardware/location/IGeofenceHardware.aidl +++ b/core/java/android/hardware/location/IGeofenceHardware.aidl @@ -18,6 +18,7 @@ package android.hardware.location; import android.location.IFusedGeofenceHardware; import android.location.IGpsGeofenceHardware; +import android.hardware.location.GeofenceHardwareRequestParcelable; import android.hardware.location.IGeofenceHardwareCallback; import android.hardware.location.IGeofenceHardwareMonitorCallback; @@ -27,9 +28,10 @@ interface IGeofenceHardware { void setFusedGeofenceHardware(in IFusedGeofenceHardware service); int[] getMonitoringTypes(); int getStatusOfMonitoringType(int monitoringType); - boolean addCircularFence(int id, int monitoringType, double lat, double longitude, - double radius, int lastTransition, int monitorTransitions, - int notificationResponsiveness, int unknownTimer,in IGeofenceHardwareCallback callback); + boolean addCircularFence( + int monitoringType, + in GeofenceHardwareRequestParcelable request, + in IGeofenceHardwareCallback callback); boolean removeGeofence(int id, int monitoringType); boolean pauseGeofence(int id, int monitoringType); boolean resumeGeofence(int id, int monitoringType, int monitorTransitions); diff --git a/core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl b/core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl index 0b6e04b..811ecd0 100644 --- a/core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl +++ b/core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl @@ -16,9 +16,10 @@ package android.hardware.location; +import android.hardware.location.GeofenceHardwareMonitorEvent; import android.location.Location; /** @hide */ oneway interface IGeofenceHardwareMonitorCallback { - void onMonitoringSystemChange(int monitoringType, boolean available, in Location location); + void onMonitoringSystemChange(in GeofenceHardwareMonitorEvent event); } |
