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
diff --git a/Android.mk b/Android.mk
index 8115472..bd88877 100644
--- a/Android.mk
+++ b/Android.mk
@@ -126,6 +126,7 @@
 	core/java/android/hardware/input/IInputDevicesChangedListener.aidl \
 	core/java/android/hardware/location/IGeofenceHardware.aidl \
 	core/java/android/hardware/location/IGeofenceHardwareCallback.aidl \
+	core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl \
 	core/java/android/hardware/usb/IUsbManager.aidl \
 	core/java/android/net/IConnectivityManager.aidl \
 	core/java/android/net/INetworkManagementEventObserver.aidl \
diff --git a/api/current.txt b/api/current.txt
index d1be295..b42ac72 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10476,13 +10476,14 @@
 package android.hardware.location {
 
   public final class GeofenceHardware {
-    method public boolean addCircularFence(int, double, double, double, int, int, int, int, int, android.hardware.location.GeofenceHardwareCallback);
-    method public int[] getMonitoringTypesAndStatus();
+    method public boolean addGeofence(int, int, android.hardware.location.GeofenceHardwareRequest, android.hardware.location.GeofenceHardwareCallback);
+    method public int[] getMonitoringTypes();
+    method public int getStatusOfMonitoringType(int);
     method public boolean pauseGeofence(int, int);
-    method public boolean registerForMonitorStateChangeCallback(int, android.hardware.location.GeofenceHardwareCallback);
+    method public boolean registerForMonitorStateChangeCallback(int, android.hardware.location.GeofenceHardwareMonitorCallback);
     method public boolean removeGeofence(int, int);
     method public boolean resumeGeofence(int, int, int);
-    method public boolean unregisterForMonitorStateChangeCallback(int, android.hardware.location.GeofenceHardwareCallback);
+    method public boolean unregisterForMonitorStateChangeCallback(int, android.hardware.location.GeofenceHardwareMonitorCallback);
     field public static final int GEOFENCE_ENTERED = 1; // 0x1
     field public static final int GEOFENCE_ERROR_ID_EXISTS = 2; // 0x2
     field public static final int GEOFENCE_ERROR_ID_UNKNOWN = 3; // 0x3
@@ -10501,13 +10502,33 @@
   public abstract class GeofenceHardwareCallback {
     ctor public GeofenceHardwareCallback();
     method public void onGeofenceAdd(int, int);
-    method public void onGeofenceChange(int, int, android.location.Location, long, int);
     method public void onGeofencePause(int, int);
     method public void onGeofenceRemove(int, int);
     method public void onGeofenceResume(int, int);
+    method public void onGeofenceTransition(int, int, android.location.Location, long, int);
+  }
+
+  public abstract class GeofenceHardwareMonitorCallback {
+    ctor public GeofenceHardwareMonitorCallback();
     method public void onMonitoringSystemChange(int, boolean, android.location.Location);
   }
 
+  public final class GeofenceHardwareRequest {
+    ctor public GeofenceHardwareRequest();
+    method public static android.hardware.location.GeofenceHardwareRequest createCircularGeofence(double, double, double);
+    method public int getLastTransition();
+    method public double getLatitude();
+    method public double getLongitude();
+    method public int getMonitorTransitions();
+    method public int getNotificationResponsiveness();
+    method public double getRadius();
+    method public int getUnknownTimer();
+    method public void setLastTransition(int);
+    method public void setMonitorTransitions(int);
+    method public void setNotificationResponsiveness(int);
+    method public void setUnknownTimer(int);
+  }
+
 }
 
 package android.hardware.usb {
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 @@
 
     private HashMap<GeofenceHardwareCallback, GeofenceHardwareCallbackWrapper>
             mCallbacks = new HashMap<GeofenceHardwareCallback, GeofenceHardwareCallbackWrapper>();
+    private HashMap<GeofenceHardwareMonitorCallback, GeofenceHardwareMonitorCallbackWrapper>
+            mMonitorCallbacks = new HashMap<GeofenceHardwareMonitorCallback,
+                    GeofenceHardwareMonitorCallbackWrapper>();
     /**
      * @hide
      */
@@ -137,8 +140,29 @@
     }
 
     /**
-     * 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 @@
      * 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 @@
      * <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 @@
      * 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 @@
      * @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 @@
    }
 
     /**
-     * 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 @@
      * @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 @@
     /**
      * 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 @@
      * 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 @@
      * @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 @@
      * @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,6 +425,38 @@
         }
     }
 
+    private void removeMonitorCallback(GeofenceHardwareMonitorCallback callback) {
+        synchronized (mMonitorCallbacks) {
+            mMonitorCallbacks.remove(callback);
+        }
+    }
+
+    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) {
+            GeofenceHardwareMonitorCallback c = mCallback.get();
+            if (c != null) c.onMonitoringSystemChange(monitoringType, available, location);
+        }
+    }
+
     class GeofenceHardwareCallbackWrapper extends IGeofenceHardwareCallback.Stub {
         private WeakReference<GeofenceHardwareCallback> mCallback;
 
@@ -398,17 +464,11 @@
             mCallback = new WeakReference<GeofenceHardwareCallback>(c);
         }
 
-        public void onMonitoringSystemChange(int monitoringType, boolean available,
-                Location location) {
-            GeofenceHardwareCallback c = mCallback.get();
-            if (c != null) c.onMonitoringSystemChange(monitoringType, available, location);
-        }
-
-        public void onGeofenceChange(int geofenceId, int transition, Location location,
+        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 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 @@
  * 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 @@
      *        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.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 @@
     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 @@
     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 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 boolean addCircularFence(int geofenceId, double latitude, double longitude,
-            double radius, int lastTransition,int monitorTransitions, int notificationResponsivenes,
-            int unknownTimer, int monitoringType, IGeofenceHardwareCallback callback) {
+    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,  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 @@
             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 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 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 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 @@
                             "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 @@
         @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 @@
 
                     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 @@
                     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 @@
         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 @@
             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 @@
             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 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 @@
 
 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 @@
 
 /** @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);
+}