summaryrefslogtreecommitdiffstats
path: root/core/java/android/hardware/location
diff options
context:
space:
mode:
authorJaikumar Ganesh <jaikumar@google.com>2013-04-17 12:19:10 -0700
committerJaikumar Ganesh <jaikumar@google.com>2013-04-17 22:18:01 -0700
commitda6508954a492f3dd4397e70e4fa08ee54bd2741 (patch)
tree925e76b5d0c132c104b3ff32a762ea2b0a12e319 /core/java/android/hardware/location
parent5584737fff6350ab09fb53e6a73bbff770930727 (diff)
downloadframeworks_base-da6508954a492f3dd4397e70e4fa08ee54bd2741.zip
frameworks_base-da6508954a492f3dd4397e70e4fa08ee54bd2741.tar.gz
frameworks_base-da6508954a492f3dd4397e70e4fa08ee54bd2741.tar.bz2
Hardware geofence API changes.
b/8631678 1.GeofenceRequest object created. 2.MonitorState moved to a new callback 3.getTypeAndStatus separated to 2 calls. 4.Binder death implemented 5.geofenceChange callback name changed. 6.Parameters rearranged in some calls. Change-Id: I8fe9621186aeb49efeb0eef1821a2556afe03cfc
Diffstat (limited to 'core/java/android/hardware/location')
-rw-r--r--core/java/android/hardware/location/GeofenceHardware.java178
-rw-r--r--core/java/android/hardware/location/GeofenceHardwareCallback.java15
-rw-r--r--core/java/android/hardware/location/GeofenceHardwareImpl.java178
-rw-r--r--core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java37
-rw-r--r--core/java/android/hardware/location/GeofenceHardwareRequest.java158
-rw-r--r--core/java/android/hardware/location/GeofenceHardwareService.java31
-rw-r--r--core/java/android/hardware/location/IGeofenceHardware.aidl16
-rw-r--r--core/java/android/hardware/location/IGeofenceHardwareCallback.aidl3
-rw-r--r--core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl24
9 files changed, 529 insertions, 111 deletions
diff --git a/core/java/android/hardware/location/GeofenceHardware.java b/core/java/android/hardware/location/GeofenceHardware.java
index 35bbb9c..e67d0d7 100644
--- a/core/java/android/hardware/location/GeofenceHardware.java
+++ b/core/java/android/hardware/location/GeofenceHardware.java
@@ -129,6 +129,9 @@ public final class GeofenceHardware {
private HashMap<GeofenceHardwareCallback, GeofenceHardwareCallbackWrapper>
mCallbacks = new HashMap<GeofenceHardwareCallback, GeofenceHardwareCallbackWrapper>();
+ private HashMap<GeofenceHardwareMonitorCallback, GeofenceHardwareMonitorCallbackWrapper>
+ mMonitorCallbacks = new HashMap<GeofenceHardwareMonitorCallback,
+ GeofenceHardwareMonitorCallbackWrapper>();
/**
* @hide
*/
@@ -137,8 +140,29 @@ public final class GeofenceHardware {
}
/**
- * Returns all the hardware geofence monitoring systems and their status.
- * Status can be one of {@link #MONITOR_CURRENTLY_AVAILABLE},
+ * Returns all the hardware geofence monitoring systems which are supported
+ *
+ * <p> Call {@link #getStatusOfMonitoringType(int)} to know the current state
+ * of a monitoring system.
+ *
+ * <p> Requires {@link android.Manifest.permission#LOCATION_HARDWARE} permission to access
+ * geofencing in hardware.
+ *
+ * @return An array of all the monitoring types.
+ * An array of length 0 is returned in case of errors.
+ */
+ public int[] getMonitoringTypes() {
+ try {
+ return mService.getMonitoringTypes();
+ } catch (RemoteException e) {
+ }
+ return new int[0];
+ }
+
+ /**
+ * Returns current status of a hardware geofence monitoring system.
+ *
+ * <p>Status can be one of {@link #MONITOR_CURRENTLY_AVAILABLE},
* {@link #MONITOR_CURRENTLY_UNAVAILABLE} or {@link #MONITOR_UNSUPPORTED}
*
* <p> Some supported hardware monitoring systems might not be available
@@ -147,18 +171,15 @@ public final class GeofenceHardware {
* geofences and will change from {@link #MONITOR_CURRENTLY_AVAILABLE} to
* {@link #MONITOR_CURRENTLY_UNAVAILABLE}.
*
- * <p> Requires {@link android.Manifest.permission#LOCATION_HARDWARE} permission to access
- * geofencing in hardware.
- *
- * @return An array indexed by the various monitoring types and their status.
- * An array of length 0 is returned in case of errors.
+ * @param monitoringType
+ * @return Current status of the monitoring type.
*/
- public int[] getMonitoringTypesAndStatus() {
+ public int getStatusOfMonitoringType(int monitoringType) {
try {
- return mService.getMonitoringTypesAndStatus();
+ return mService.getStatusOfMonitoringType(monitoringType);
} catch (RemoteException e) {
+ return MONITOR_UNSUPPORTED;
}
- return new int[0];
}
/**
@@ -167,8 +188,10 @@ public final class GeofenceHardware {
* <p> When the device detects that is has entered, exited or is uncertain
* about the area specified by the geofence, the given callback will be called.
*
- * <p> The {@link GeofenceHardwareCallback#onGeofenceChange} callback will be called,
- * with the following parameters
+ * <p> If this call returns true, it means that the geofence has been sent to the hardware.
+ * {@link GeofenceHardwareCallback#onGeofenceAdd} will be called with the result of the
+ * add call from the hardware. The {@link GeofenceHardwareCallback#onGeofenceAdd} will be
+ * called with the following parameters when a transition event occurs.
* <ul>
* <li> The geofence Id
* <li> The location object indicating the last known location.
@@ -195,43 +218,46 @@ public final class GeofenceHardware {
* which abstracts the hardware should be used instead. All the checks are done by the higher
* level public API. Any needed locking should be handled by the higher level API.
*
- * @param latitude Latitude of the area to be monitored.
- * @param longitude Longitude of the area to be monitored.
- * @param radius Radius (in meters) of the area to be monitored.
- * @param lastTransition The current state of the geofence. Can be one of
- * {@link #GEOFENCE_ENTERED}, {@link #GEOFENCE_EXITED},
- * {@link #GEOFENCE_UNCERTAIN}.
- * @param monitorTransitions Bitwise OR of {@link #GEOFENCE_ENTERED},
- * {@link #GEOFENCE_EXITED}, {@link #GEOFENCE_UNCERTAIN}
- * @param notificationResponsivenes Defines the best-effort description
- * of how soon should the callback be called when the transition
- * associated with the Geofence is triggered. For instance, if
- * set to 1000 millseconds with {@link #GEOFENCE_ENTERED},
- * the callback will be called 1000 milliseconds within entering
- * the geofence. This parameter is defined in milliseconds.
- * @param unknownTimer The time limit after which the
- * {@link #GEOFENCE_UNCERTAIN} transition
- * should be triggered. This paramter is defined in milliseconds.
+ * <p> Create a geofence request object using the methods in {@link GeofenceHardwareRequest} to
+ * set all the characteristics of the geofence. Use the created GeofenceHardwareRequest object
+ * in this call.
+ *
+ * @param geofenceId The id associated with the geofence.
* @param monitoringType The type of the hardware subsystem that should be used
* to monitor the geofence.
+ * @param geofenceRequest The {@link GeofenceHardwareRequest} object associated with the
+ * geofence.
* @param callback {@link GeofenceHardwareCallback} that will be use to notify the
* transition.
- * @return true on success.
+ * @return true when the geofence is successfully sent to the hardware for addition.
+ * @throws IllegalArgumentException when the geofence request type is not supported.
*/
- public boolean addCircularFence(int geofenceId, double latitude, double longitude,
- double radius, int lastTransition,int monitorTransitions, int notificationResponsivenes,
- int unknownTimer, int monitoringType, GeofenceHardwareCallback callback) {
+ public boolean addGeofence(int geofenceId, int monitoringType, GeofenceHardwareRequest
+ geofenceRequest, GeofenceHardwareCallback callback) {
try {
- return mService.addCircularFence(geofenceId, latitude, longitude, radius,
- lastTransition, monitorTransitions, notificationResponsivenes, unknownTimer,
- monitoringType, getCallbackWrapper(callback));
+ 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(),
+ getCallbackWrapper(callback));
+ } else {
+ throw new IllegalArgumentException("Geofence Request type not supported");
+ }
} catch (RemoteException e) {
}
return false;
}
/**
- * Removes a geofence added by {@link #addCircularFence} call.
+ * Removes a geofence added by {@link #addGeofence} call.
+ *
+ * <p> If this call returns true, it means that the geofence has been sent to the hardware.
+ * {@link GeofenceHardwareCallback#onGeofenceRemove} will be called with the result of the
+ * remove call from the hardware.
*
* <p> Requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission when
* {@link #MONITORING_TYPE_GPS_HARDWARE} is used.
@@ -246,7 +272,7 @@ public final class GeofenceHardware {
* @param geofenceId The id of the geofence.
* @param monitoringType The type of the hardware subsystem that should be used
* to monitor the geofence.
- * @return true on success.
+ * @return true when the geofence is successfully sent to the hardware for removal. .
*/
public boolean removeGeofence(int geofenceId, int monitoringType) {
try {
@@ -257,7 +283,11 @@ public final class GeofenceHardware {
}
/**
- * Pauses the monitoring of a geofence added by {@link #addCircularFence} call.
+ * Pauses the monitoring of a geofence added by {@link #addGeofence} call.
+ *
+ * <p> If this call returns true, it means that the geofence has been sent to the hardware.
+ * {@link GeofenceHardwareCallback#onGeofencePause} will be called with the result of the
+ * pause call from the hardware.
*
* <p> Requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission when
* {@link #MONITORING_TYPE_GPS_HARDWARE} is used.
@@ -272,7 +302,7 @@ public final class GeofenceHardware {
* @param geofenceId The id of the geofence.
* @param monitoringType The type of the hardware subsystem that should be used
* to monitor the geofence.
- * @return true on success.
+ * @return true when the geofence is successfully sent to the hardware for pausing.
*/
public boolean pauseGeofence(int geofenceId, int monitoringType) {
try {
@@ -285,6 +315,10 @@ public final class GeofenceHardware {
/**
* Resumes the monitoring of a geofence added by {@link #pauseGeofence} call.
*
+ * <p> If this call returns true, it means that the geofence has been sent to the hardware.
+ * {@link GeofenceHardwareCallback#onGeofenceResume} will be called with the result of the
+ * resume call from the hardware.
+ *
* <p> Requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission when
* {@link #MONITORING_TYPE_GPS_HARDWARE} is used.
*
@@ -296,15 +330,15 @@ public final class GeofenceHardware {
* level public API. Any needed locking should be handled by the higher level API.
*
* @param geofenceId The id of the geofence.
- * @param monitorTransition Bitwise OR of {@link #GEOFENCE_ENTERED},
- * {@link #GEOFENCE_EXITED}, {@link #GEOFENCE_UNCERTAIN}
* @param monitoringType The type of the hardware subsystem that should be used
* to monitor the geofence.
- * @return true on success.
+ * @param monitorTransition Bitwise OR of {@link #GEOFENCE_ENTERED},
+ * {@link #GEOFENCE_EXITED}, {@link #GEOFENCE_UNCERTAIN}
+ * @return true when the geofence is successfully sent to the hardware for resumption.
*/
- public boolean resumeGeofence(int geofenceId, int monitorTransition, int monitoringType) {
+ public boolean resumeGeofence(int geofenceId, int monitoringType, int monitorTransition) {
try {
- return mService.resumeGeofence(geofenceId, monitorTransition, monitoringType);
+ return mService.resumeGeofence(geofenceId, monitoringType, monitorTransition);
} catch (RemoteException e) {
}
return false;
@@ -333,10 +367,10 @@ public final class GeofenceHardware {
* @return true on success
*/
public boolean registerForMonitorStateChangeCallback(int monitoringType,
- GeofenceHardwareCallback callback) {
+ GeofenceHardwareMonitorCallback callback) {
try {
return mService.registerForMonitorStateChangeCallback(monitoringType,
- getCallbackWrapper(callback));
+ getMonitorCallbackWrapper(callback));
} catch (RemoteException e) {
}
return false;
@@ -361,12 +395,12 @@ public final class GeofenceHardware {
* @return true on success
*/
public boolean unregisterForMonitorStateChangeCallback(int monitoringType,
- GeofenceHardwareCallback callback) {
+ GeofenceHardwareMonitorCallback callback) {
boolean result = false;
try {
result = mService.unregisterForMonitorStateChangeCallback(monitoringType,
- getCallbackWrapper(callback));
- if (result) removeCallback(callback);
+ getMonitorCallbackWrapper(callback));
+ if (result) removeMonitorCallback(callback);
} catch (RemoteException e) {
}
@@ -391,24 +425,50 @@ public final class GeofenceHardware {
}
}
- class GeofenceHardwareCallbackWrapper extends IGeofenceHardwareCallback.Stub {
- private WeakReference<GeofenceHardwareCallback> mCallback;
+ private void removeMonitorCallback(GeofenceHardwareMonitorCallback callback) {
+ synchronized (mMonitorCallbacks) {
+ mMonitorCallbacks.remove(callback);
+ }
+ }
- GeofenceHardwareCallbackWrapper(GeofenceHardwareCallback c) {
- mCallback = new WeakReference<GeofenceHardwareCallback>(c);
+ private GeofenceHardwareMonitorCallbackWrapper getMonitorCallbackWrapper(
+ GeofenceHardwareMonitorCallback callback) {
+ synchronized (mMonitorCallbacks) {
+ GeofenceHardwareMonitorCallbackWrapper wrapper = mMonitorCallbacks.get(callback);
+ if (wrapper == null) {
+ wrapper = new GeofenceHardwareMonitorCallbackWrapper(callback);
+ mMonitorCallbacks.put(callback, wrapper);
+ }
+ return wrapper;
+ }
+ }
+
+ class GeofenceHardwareMonitorCallbackWrapper extends IGeofenceHardwareMonitorCallback.Stub {
+ private WeakReference<GeofenceHardwareMonitorCallback> mCallback;
+
+ GeofenceHardwareMonitorCallbackWrapper(GeofenceHardwareMonitorCallback c) {
+ mCallback = new WeakReference<GeofenceHardwareMonitorCallback>(c);
}
public void onMonitoringSystemChange(int monitoringType, boolean available,
Location location) {
- GeofenceHardwareCallback c = mCallback.get();
+ GeofenceHardwareMonitorCallback c = mCallback.get();
if (c != null) c.onMonitoringSystemChange(monitoringType, available, location);
}
+ }
+
+ class GeofenceHardwareCallbackWrapper extends IGeofenceHardwareCallback.Stub {
+ private WeakReference<GeofenceHardwareCallback> mCallback;
- public void onGeofenceChange(int geofenceId, int transition, Location location,
+ GeofenceHardwareCallbackWrapper(GeofenceHardwareCallback c) {
+ mCallback = new WeakReference<GeofenceHardwareCallback>(c);
+ }
+
+ public void onGeofenceTransition(int geofenceId, int transition, Location location,
long timestamp, int monitoringType) {
GeofenceHardwareCallback c = mCallback.get();
if (c != null) {
- c.onGeofenceChange(geofenceId, transition, location, timestamp,
+ c.onGeofenceTransition(geofenceId, transition, location, timestamp,
monitoringType);
}
}
@@ -428,7 +488,9 @@ public final class GeofenceHardware {
public void onGeofencePause(int geofenceId, int status) {
GeofenceHardwareCallback c = mCallback.get();
- if (c != null) c.onGeofencePause(geofenceId, status);
+ if (c != null) {
+ c.onGeofencePause(geofenceId, status);
+ }
}
public void onGeofenceResume(int geofenceId, int status) {
diff --git a/core/java/android/hardware/location/GeofenceHardwareCallback.java b/core/java/android/hardware/location/GeofenceHardwareCallback.java
index 8ab582a..6cad3da 100644
--- a/core/java/android/hardware/location/GeofenceHardwareCallback.java
+++ b/core/java/android/hardware/location/GeofenceHardwareCallback.java
@@ -22,19 +22,6 @@ import android.location.Location;
* The callback class associated with the APIs in {@link GeofenceHardware}
*/
public abstract class GeofenceHardwareCallback {
-
- /**
- * The callback called when the state of a monitoring system changes.
- * {@link GeofenceHardware#MONITORING_TYPE_GPS_HARDWARE} is an example of a
- * monitoring system.
- *
- * @param monitoringType The type of the monitoring system.
- * @param available Indicates whether the system is currently available or not.
- * @param location The last known location according to the monitoring system.
- */
- public void onMonitoringSystemChange(int monitoringType, boolean available, Location location) {
- }
-
/**
* The callback called when there is a transition to report for the specific
* geofence.
@@ -47,7 +34,7 @@ public abstract class GeofenceHardwareCallback {
* detected
* @param monitoringType Type of the monitoring system.
*/
- public void onGeofenceChange(int geofenceId, int transition, Location location,
+ public void onGeofenceTransition(int geofenceId, int transition, Location location,
long timestamp, int monitoringType) {
}
diff --git a/core/java/android/hardware/location/GeofenceHardwareImpl.java b/core/java/android/hardware/location/GeofenceHardwareImpl.java
index 21f1ea6..a62b660 100644
--- a/core/java/android/hardware/location/GeofenceHardwareImpl.java
+++ b/core/java/android/hardware/location/GeofenceHardwareImpl.java
@@ -21,8 +21,10 @@ import android.content.pm.PackageManager;
import android.location.IGpsGeofenceHardware;
import android.location.Location;
import android.location.LocationManager;
+import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
@@ -48,8 +50,9 @@ public final class GeofenceHardwareImpl {
private PowerManager.WakeLock mWakeLock;
private SparseArray<IGeofenceHardwareCallback> mGeofences =
new SparseArray<IGeofenceHardwareCallback>();
- private ArrayList<IGeofenceHardwareCallback>[] mCallbacks =
+ private ArrayList<IGeofenceHardwareMonitorCallback>[] mCallbacks =
new ArrayList[GeofenceHardware.NUM_MONITORS];
+ private ArrayList<Reaper> mReapers = new ArrayList<Reaper>();
private IGpsGeofenceHardware mGpsService;
@@ -63,11 +66,18 @@ public final class GeofenceHardwareImpl {
private static final int RESUME_GEOFENCE_CALLBACK = 5;
private static final int ADD_GEOFENCE = 6;
private static final int REMOVE_GEOFENCE = 7;
+ private static final int GEOFENCE_CALLBACK_BINDER_DIED = 8;
// mCallbacksHandler message types
private static final int GPS_GEOFENCE_STATUS = 1;
private static final int CALLBACK_ADD = 2;
private static final int CALLBACK_REMOVE = 3;
+ private static final int MONITOR_CALLBACK_BINDER_DIED = 4;
+
+ // mReaperHandler message types
+ private static final int REAPER_GEOFENCE_ADDED = 1;
+ private static final int REAPER_MONITOR_CALLBACK_ADDED = 2;
+ private static final int REAPER_REMOVED = 3;
// The following constants need to match GpsLocationFlags enum in gps.h
private static final int LOCATION_INVALID = 0;
@@ -151,15 +161,28 @@ public final class GeofenceHardwareImpl {
}
}
- public int[] getMonitoringTypesAndStatus() {
+ public int[] getMonitoringTypes() {
synchronized (mSupportedMonitorTypes) {
- return mSupportedMonitorTypes;
+ if (mSupportedMonitorTypes[GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE] !=
+ GeofenceHardware.MONITOR_UNSUPPORTED) {
+ return new int[] {GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE};
+ }
+ return new int[0];
+ }
+ }
+
+ public int getStatusOfMonitoringType(int monitoringType) {
+ synchronized (mSupportedMonitorTypes) {
+ if (monitoringType >= mSupportedMonitorTypes.length || monitoringType < 0) {
+ throw new IllegalArgumentException("Unknown monitoring type");
+ }
+ return mSupportedMonitorTypes[monitoringType];
}
}
- public boolean addCircularFence(int geofenceId, double latitude, double longitude,
- double radius, int lastTransition,int monitorTransitions, int notificationResponsivenes,
- int unknownTimer, int monitoringType, IGeofenceHardwareCallback callback) {
+ public boolean addCircularFence(int geofenceId, int monitoringType, double latitude,
+ double longitude, double radius, int lastTransition,int monitorTransitions,
+ int notificationResponsivenes, int unknownTimer, IGeofenceHardwareCallback callback) {
// This API is not thread safe. Operations on the same geofence need to be serialized
// by upper layers
if (DEBUG) {
@@ -190,7 +213,11 @@ public final class GeofenceHardwareImpl {
default:
result = false;
}
- if (!result) {
+ if (result) {
+ m = mReaperHandler.obtainMessage(REAPER_GEOFENCE_ADDED, callback);
+ m.arg1 = monitoringType;
+ mReaperHandler.sendMessage(m);
+ } else {
m = mGeofenceHandler.obtainMessage(REMOVE_GEOFENCE);
m.arg1 = geofenceId;
mGeofenceHandler.sendMessage(m);
@@ -245,7 +272,7 @@ public final class GeofenceHardwareImpl {
}
- public boolean resumeGeofence(int geofenceId, int monitorTransition, int monitoringType) {
+ public boolean resumeGeofence(int geofenceId, int monitoringType, int monitorTransition) {
// This API is not thread safe. Operations on the same geofence need to be serialized
// by upper layers
if (DEBUG) Log.d(TAG, "Resume Geofence: GeofenceId: " + geofenceId);
@@ -268,7 +295,12 @@ public final class GeofenceHardwareImpl {
}
public boolean registerForMonitorStateChangeCallback(int monitoringType,
- IGeofenceHardwareCallback callback) {
+ IGeofenceHardwareMonitorCallback callback) {
+ Message reaperMessage =
+ mReaperHandler.obtainMessage(REAPER_MONITOR_CALLBACK_ADDED, callback);
+ reaperMessage.arg1 = monitoringType;
+ mReaperHandler.sendMessage(reaperMessage);
+
Message m = mCallbacksHandler.obtainMessage(CALLBACK_ADD, callback);
m.arg1 = monitoringType;
mCallbacksHandler.sendMessage(m);
@@ -276,7 +308,7 @@ public final class GeofenceHardwareImpl {
}
public boolean unregisterForMonitorStateChangeCallback(int monitoringType,
- IGeofenceHardwareCallback callback) {
+ IGeofenceHardwareMonitorCallback callback) {
Message m = mCallbacksHandler.obtainMessage(CALLBACK_REMOVE, callback);
m.arg1 = monitoringType;
mCallbacksHandler.sendMessage(m);
@@ -477,13 +509,25 @@ public final class GeofenceHardwareImpl {
"Location: " + geofenceTransition.mLocation + ":" + mGeofences);
try {
- callback.onGeofenceChange(
+ callback.onGeofenceTransition(
geofenceTransition.mGeofenceId, geofenceTransition.mTransition,
geofenceTransition.mLocation, geofenceTransition.mTimestamp,
GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE);
} catch (RemoteException e) {}
releaseWakeLock();
break;
+ case GEOFENCE_CALLBACK_BINDER_DIED:
+ // Find all geofences associated with this callback and remove them.
+ callback = (IGeofenceHardwareCallback) (msg.obj);
+ if (DEBUG) Log.d(TAG, "Geofence callback reaped:" + callback);
+ int monitoringType = msg.arg1;
+ for (int i = 0; i < mGeofences.size(); i++) {
+ if (mGeofences.valueAt(i).equals(callback)) {
+ geofenceId = mGeofences.keyAt(i);
+ removeGeofence(mGeofences.keyAt(i), monitoringType);
+ mGeofences.remove(geofenceId);
+ }
+ }
}
}
};
@@ -493,8 +537,8 @@ public final class GeofenceHardwareImpl {
@Override
public void handleMessage(Message msg) {
int monitoringType;
- ArrayList<IGeofenceHardwareCallback> callbackList;
- IGeofenceHardwareCallback callback;
+ ArrayList<IGeofenceHardwareMonitorCallback> callbackList;
+ IGeofenceHardwareMonitorCallback callback;
switch (msg.what) {
case GPS_GEOFENCE_STATUS:
@@ -508,7 +552,7 @@ public final class GeofenceHardwareImpl {
if (DEBUG) Log.d(TAG, "MonitoringSystemChangeCallback: GPS : " + available);
- for (IGeofenceHardwareCallback c: callbackList) {
+ for (IGeofenceHardwareMonitorCallback c: callbackList) {
try {
c.onMonitoringSystemChange(
GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE, available,
@@ -519,22 +563,71 @@ public final class GeofenceHardwareImpl {
break;
case CALLBACK_ADD:
monitoringType = msg.arg1;
- callback = (IGeofenceHardwareCallback) msg.obj;
+ callback = (IGeofenceHardwareMonitorCallback) msg.obj;
callbackList = mCallbacks[monitoringType];
if (callbackList == null) {
- callbackList = new ArrayList<IGeofenceHardwareCallback>();
+ callbackList = new ArrayList<IGeofenceHardwareMonitorCallback>();
mCallbacks[monitoringType] = callbackList;
}
if (!callbackList.contains(callback)) callbackList.add(callback);
break;
case CALLBACK_REMOVE:
monitoringType = msg.arg1;
- callback = (IGeofenceHardwareCallback) msg.obj;
+ callback = (IGeofenceHardwareMonitorCallback) msg.obj;
callbackList = mCallbacks[monitoringType];
if (callbackList != null) {
callbackList.remove(callback);
}
break;
+ case MONITOR_CALLBACK_BINDER_DIED:
+ callback = (IGeofenceHardwareMonitorCallback) msg.obj;
+ if (DEBUG) Log.d(TAG, "Monitor callback reaped:" + callback);
+ callbackList = mCallbacks[msg.arg1];
+ if (callbackList != null && callbackList.contains(callback)) {
+ callbackList.remove(callback);
+ }
+ }
+ }
+ };
+
+ // All operations on mReaper
+ private Handler mReaperHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ Reaper r;
+ IGeofenceHardwareCallback callback;
+ IGeofenceHardwareMonitorCallback monitorCallback;
+ int monitoringType;
+
+ switch (msg.what) {
+ case REAPER_GEOFENCE_ADDED:
+ callback = (IGeofenceHardwareCallback) msg.obj;
+ monitoringType = msg.arg1;
+ r = new Reaper(callback, monitoringType);
+ if (!mReapers.contains(r)) {
+ mReapers.add(r);
+ IBinder b = callback.asBinder();
+ try {
+ b.linkToDeath(r, 0);
+ } catch (RemoteException e) {}
+ }
+ break;
+ case REAPER_MONITOR_CALLBACK_ADDED:
+ monitorCallback = (IGeofenceHardwareMonitorCallback) msg.obj;
+ monitoringType = msg.arg1;
+
+ r = new Reaper(monitorCallback, monitoringType);
+ if (!mReapers.contains(r)) {
+ mReapers.add(r);
+ IBinder b = monitorCallback.asBinder();
+ try {
+ b.linkToDeath(r, 0);
+ } catch (RemoteException e) {}
+ }
+ break;
+ case REAPER_REMOVED:
+ r = (Reaper) msg.obj;
+ mReapers.remove(r);
}
}
};
@@ -567,6 +660,57 @@ public final class GeofenceHardwareImpl {
return RESOLUTION_LEVEL_NONE;
}
+ class Reaper implements IBinder.DeathRecipient {
+ private IGeofenceHardwareMonitorCallback mMonitorCallback;
+ private IGeofenceHardwareCallback mCallback;
+ private int mMonitoringType;
+
+ Reaper(IGeofenceHardwareCallback c, int monitoringType) {
+ mCallback = c;
+ mMonitoringType = monitoringType;
+ }
+
+ Reaper(IGeofenceHardwareMonitorCallback c, int monitoringType) {
+ mMonitorCallback = c;
+ mMonitoringType = monitoringType;
+ }
+
+ @Override
+ public void binderDied() {
+ Message m;
+ if (mCallback != null) {
+ m = mGeofenceHandler.obtainMessage(GEOFENCE_CALLBACK_BINDER_DIED, mCallback);
+ m.arg1 = mMonitoringType;
+ mGeofenceHandler.sendMessage(m);
+ } else if (mMonitorCallback != null) {
+ m = mCallbacksHandler.obtainMessage(MONITOR_CALLBACK_BINDER_DIED, mMonitorCallback);
+ m.arg1 = mMonitoringType;
+ mCallbacksHandler.sendMessage(m);
+ }
+ Message reaperMessage = mReaperHandler.obtainMessage(REAPER_REMOVED, this);
+ mReaperHandler.sendMessage(reaperMessage);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 17;
+ result = 31 * result + (mCallback != null ? mCallback.hashCode() : 0);
+ result = 31 * result + (mMonitorCallback != null ? mMonitorCallback.hashCode() : 0);
+ result = 31 * result + mMonitoringType;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) return false;
+ if (obj == this) return true;
+
+ Reaper rhs = (Reaper) obj;
+ return rhs.mCallback == mCallback && rhs.mMonitorCallback == mMonitorCallback &&
+ rhs.mMonitoringType == mMonitoringType;
+ }
+ }
+
int getAllowedResolutionLevel(int pid, int uid) {
if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
pid, uid) == PackageManager.PERMISSION_GRANTED) {
diff --git a/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java b/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java
new file mode 100644
index 0000000..b8e927e
--- /dev/null
+++ b/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 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;
+
+/**
+ * The callback class associated with the status change of hardware montiors
+ * 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
+ *
+ * @param monitoringType The type of the monitoring system.
+ * @param available Indicates whether the system is currenty available or not.
+ * @param location The last known location according to the monitoring system.
+ */
+ public void onMonitoringSystemChange(int monitoringType, boolean available, Location location) {
+ }
+}
diff --git a/core/java/android/hardware/location/GeofenceHardwareRequest.java b/core/java/android/hardware/location/GeofenceHardwareRequest.java
new file mode 100644
index 0000000..6e7b592
--- /dev/null
+++ b/core/java/android/hardware/location/GeofenceHardwareRequest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2013 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;
+
+/**
+ * This class represents the characteristics of the geofence.
+ *
+ * <p> Use this in conjunction with {@link GeofenceHardware} APIs.
+ */
+
+public final class GeofenceHardwareRequest {
+ static final int GEOFENCE_TYPE_CIRCLE = 0;
+ private int mType;
+ private double mLatitude;
+ private double mLongitude;
+ private double mRadius;
+ private int mLastTransition = GeofenceHardware.GEOFENCE_UNCERTAIN;
+ private int mUnknownTimer = 30000; // 30 secs
+ private int mMonitorTransitions = GeofenceHardware.GEOFENCE_UNCERTAIN |
+ GeofenceHardware.GEOFENCE_ENTERED | GeofenceHardware.GEOFENCE_EXITED;
+ private int mNotificationResponsiveness = 5000; // 5 secs
+
+ private void setCircularGeofence(double latitude, double longitude, double radius) {
+ mLatitude = latitude;
+ mLongitude = longitude;
+ mRadius = radius;
+ mType = GEOFENCE_TYPE_CIRCLE;
+ }
+
+ /**
+ * Create a circular geofence.
+ *
+ * @param latitude Latitude of the geofence
+ * @param longitude Longitude of the geofence
+ * @param radius Radius of the geofence (in meters)
+ */
+ public static GeofenceHardwareRequest createCircularGeofence(double latitude,
+ double longitude, double radius) {
+ GeofenceHardwareRequest geofenceRequest = new GeofenceHardwareRequest();
+ geofenceRequest.setCircularGeofence(latitude, longitude, radius);
+ return geofenceRequest;
+ }
+
+ /**
+ * Set the last known transition of the geofence.
+ *
+ * @param lastTransition The current state of the geofence. Can be one of
+ * {@link GeofenceHardware#GEOFENCE_ENTERED}, {@link GeofenceHardware#GEOFENCE_EXITED},
+ * {@link GeofenceHardware#GEOFENCE_UNCERTAIN}.
+ */
+ public void setLastTransition(int lastTransition) {
+ mLastTransition = lastTransition;
+ }
+
+ /**
+ * Set the unknown timer for this geofence.
+ *
+ * @param unknownTimer The time limit after which the
+ * {@link GeofenceHardware#GEOFENCE_UNCERTAIN} transition
+ * should be triggered. This paramter is defined in milliseconds.
+ */
+ public void setUnknownTimer(int unknownTimer) {
+ mUnknownTimer = unknownTimer;
+ }
+
+ /**
+ * Set the transitions to be monitored.
+ *
+ * @param monitorTransitions Bitwise OR of {@link GeofenceHardware#GEOFENCE_ENTERED},
+ * {@link GeofenceHardware#GEOFENCE_EXITED}, {@link GeofenceHardware#GEOFENCE_UNCERTAIN}
+ */
+ public void setMonitorTransitions(int monitorTransitions) {
+ mMonitorTransitions = monitorTransitions;
+ }
+
+ /**
+ * Set the notification responsiveness of the geofence.
+ *
+ * @param notificationResponsiveness (milliseconds) Defines the best-effort description
+ * of how soon should the callback be called when the transition
+ * associated with the Geofence is triggered. For instance, if
+ * set to 1000 millseconds with {@link GeofenceHardware#GEOFENCE_ENTERED},
+ * the callback will be called 1000 milliseconds within entering
+ * the geofence.
+ */
+ public void setNotificationResponsiveness(int notificationResponsiveness) {
+ mNotificationResponsiveness = notificationResponsiveness;
+ }
+
+ /**
+ * Returns the latitude of this geofence.
+ */
+ public double getLatitude() {
+ return mLatitude;
+ }
+
+ /**
+ * Returns the longitude of this geofence.
+ */
+ public double getLongitude() {
+ return mLongitude;
+ }
+
+ /**
+ * Returns the radius of this geofence.
+ */
+ public double getRadius() {
+ return mRadius;
+ }
+
+ /**
+ * Returns transitions monitored for this geofence.
+ */
+ public int getMonitorTransitions() {
+ return mMonitorTransitions;
+ }
+
+ /**
+ * Returns the unknownTimer of this geofence.
+ */
+ public int getUnknownTimer() {
+ return mUnknownTimer;
+ }
+
+ /**
+ * Returns the notification responsiveness of this geofence.
+ */
+ public int getNotificationResponsiveness() {
+ return mNotificationResponsiveness;
+ }
+
+ /**
+ * Returns the last transition of this geofence.
+ */
+ public int getLastTransition() {
+ return mLastTransition;
+ }
+
+ int getType() {
+ return mType;
+ }
+}
diff --git a/core/java/android/hardware/location/GeofenceHardwareService.java b/core/java/android/hardware/location/GeofenceHardwareService.java
index 0eccee6..3bc70ee 100644
--- a/core/java/android/hardware/location/GeofenceHardwareService.java
+++ b/core/java/android/hardware/location/GeofenceHardwareService.java
@@ -68,23 +68,28 @@ public class GeofenceHardwareService extends Service {
mGeofenceHardwareImpl.setGpsHardwareGeofence(service);
}
- public int[] getMonitoringTypesAndStatus() {
+ public int[] getMonitoringTypes() {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
"Location Hardware permission not granted to access hardware geofence");
- return mGeofenceHardwareImpl.getMonitoringTypesAndStatus();
+ return mGeofenceHardwareImpl.getMonitoringTypes();
}
- public boolean addCircularFence(int id, double lat, double longitude, double radius,
- int lastTransition, int monitorTransitions, int
- notificationResponsiveness, int unknownTimer, int monitoringType,
- IGeofenceHardwareCallback callback) {
+ public int getStatusOfMonitoringType(int monitoringType) {
+ mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
+ "Location Hardware permission not granted to access hardware geofence");
+
+ 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) {
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, lat, longitude, radius,
- lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer,
- monitoringType, callback);
+ return mGeofenceHardwareImpl.addCircularFence(id, monitoringType, lat, longitude,
+ radius, lastTransition, monitorTransitions, notificationResponsiveness,
+ unknownTimer, callback);
}
public boolean removeGeofence(int id, int monitoringType) {
@@ -103,16 +108,16 @@ public class GeofenceHardwareService extends Service {
return mGeofenceHardwareImpl.pauseGeofence(id, monitoringType);
}
- public boolean resumeGeofence(int id, int monitorTransitions, int monitoringType) {
+ public boolean resumeGeofence(int id, int monitoringType, int monitorTransitions) {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
"Location Hardware permission not granted to access hardware geofence");
checkPermission(Binder.getCallingPid(), Binder.getCallingUid(), monitoringType);
- return mGeofenceHardwareImpl.resumeGeofence(id, monitorTransitions, monitoringType);
+ return mGeofenceHardwareImpl.resumeGeofence(id, monitoringType, monitorTransitions);
}
public boolean registerForMonitorStateChangeCallback(int monitoringType,
- IGeofenceHardwareCallback callback) {
+ IGeofenceHardwareMonitorCallback callback) {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
"Location Hardware permission not granted to access hardware geofence");
@@ -122,7 +127,7 @@ public class GeofenceHardwareService extends Service {
}
public boolean unregisterForMonitorStateChangeCallback(int monitoringType,
- IGeofenceHardwareCallback callback) {
+ IGeofenceHardwareMonitorCallback callback) {
mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
"Location Hardware permission not granted to access hardware geofence");
diff --git a/core/java/android/hardware/location/IGeofenceHardware.aidl b/core/java/android/hardware/location/IGeofenceHardware.aidl
index 4ba02b8..6900070 100644
--- a/core/java/android/hardware/location/IGeofenceHardware.aidl
+++ b/core/java/android/hardware/location/IGeofenceHardware.aidl
@@ -18,19 +18,21 @@ package android.hardware.location;
import android.location.IGpsGeofenceHardware;
import android.hardware.location.IGeofenceHardwareCallback;
+import android.hardware.location.IGeofenceHardwareMonitorCallback;
/** @hide */
interface IGeofenceHardware {
void setGpsGeofenceHardware(in IGpsGeofenceHardware service);
- int[] getMonitoringTypesAndStatus();
- boolean addCircularFence(int id, double lat, double longitude, double radius,
- int lastTransition, int monitorTransitions, int notificationResponsiveness,
- int unknownTimer, int monitoringType, in IGeofenceHardwareCallback callback);
+ 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 removeGeofence(int id, int monitoringType);
boolean pauseGeofence(int id, int monitoringType);
- boolean resumeGeofence(int id, int monitorTransitions, int monitoringType);
+ boolean resumeGeofence(int id, int monitoringType, int monitorTransitions);
boolean registerForMonitorStateChangeCallback(int monitoringType,
- IGeofenceHardwareCallback callback);
+ IGeofenceHardwareMonitorCallback callback);
boolean unregisterForMonitorStateChangeCallback(int monitoringType,
- IGeofenceHardwareCallback callback);
+ IGeofenceHardwareMonitorCallback callback);
}
diff --git a/core/java/android/hardware/location/IGeofenceHardwareCallback.aidl b/core/java/android/hardware/location/IGeofenceHardwareCallback.aidl
index 678fc49..3a8f430 100644
--- a/core/java/android/hardware/location/IGeofenceHardwareCallback.aidl
+++ b/core/java/android/hardware/location/IGeofenceHardwareCallback.aidl
@@ -20,8 +20,7 @@ import android.location.Location;
/** @hide */
oneway interface IGeofenceHardwareCallback {
- void onMonitoringSystemChange(int monitoringType, boolean available, in Location location);
- void onGeofenceChange(int geofenceId, int transition, in Location location,
+ void onGeofenceTransition(int geofenceId, int transition, in Location location,
long timestamp, int monitoringType);
void onGeofenceAdd(int geofenceId, int status);
void onGeofenceRemove(int geofenceId, int status);
diff --git a/core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl b/core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl
new file mode 100644
index 0000000..0b6e04b
--- /dev/null
+++ b/core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2013 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;
+
+/** @hide */
+oneway interface IGeofenceHardwareMonitorCallback {
+ void onMonitoringSystemChange(int monitoringType, boolean available, in Location location);
+}