Add a status callback for location batching in FLP HAL

-Allows GmsCore to know when location is unsuccessful so
 it can switch to a SW solution.

Change-Id: I3d1df7b828f7fb189446881eea87d9a952310614
diff --git a/core/java/android/hardware/location/IFusedLocationHardwareSink.aidl b/core/java/android/hardware/location/IFusedLocationHardwareSink.aidl
index 2107ae8..c99cb0c 100644
--- a/core/java/android/hardware/location/IFusedLocationHardwareSink.aidl
+++ b/core/java/android/hardware/location/IFusedLocationHardwareSink.aidl
@@ -44,4 +44,10 @@
      * capabilities.  Should be called immediatly after init.
      */
     void onCapabilities(int capabilities) = 2;
+
+    /**
+     * Event generated from FLP HAL when the status of location batching
+     * changes (location is successful/unsuccessful).
+     */
+    void onStatusChanged(int status) = 3;
 }
\ No newline at end of file
diff --git a/location/lib/java/com/android/location/provider/FusedLocationHardware.java b/location/lib/java/com/android/location/provider/FusedLocationHardware.java
index 44cb1990..cbe404b7 100644
--- a/location/lib/java/com/android/location/provider/FusedLocationHardware.java
+++ b/location/lib/java/com/android/location/provider/FusedLocationHardware.java
@@ -57,6 +57,11 @@
         public void onCapabilities(int capabilities) {
             dispatchCapabilities(capabilities);
         }
+
+        @Override
+        public void onStatusChanged(int status) {
+            dispatchStatus(status);
+        }
     };
 
     /**
@@ -210,6 +215,7 @@
         public static final int DISPATCH_LOCATION = 1;
         public static final int DISPATCH_DIAGNOSTIC_DATA = 2;
         public static final int DISPATCH_CAPABILITIES = 3;
+        public static final int DISPATCH_STATUS = 4;
 
         public DispatcherHandler(Looper looper) {
             super(looper, null /*callback*/ , true /*async*/);
@@ -228,6 +234,9 @@
                 case DISPATCH_CAPABILITIES:
                     command.dispatchCapabilities();
                     break;
+                case DISPATCH_STATUS:
+                    command.dispatchStatus();
+                    break;
                 default:
                     Log.e(TAG, "Invalid dispatch message");
                     break;
@@ -240,16 +249,19 @@
         private final Location[] mLocations;
         private final String mData;
         private final int mCapabilities;
+        private final int mStatus;
 
         public MessageCommand(
                 FusedLocationHardwareSink sink,
                 Location[] locations,
                 String data,
-                int capabilities) {
+                int capabilities,
+                int status) {
             mSink = sink;
             mLocations = locations;
             mData = data;
             mCapabilities = capabilities;
+            mStatus = status;
         }
 
         public void dispatchLocation() {
@@ -263,6 +275,10 @@
         public void dispatchCapabilities() {
             mSink.onCapabilities(mCapabilities);
         }
+
+        public void dispatchStatus() {
+            mSink.onStatusChanged(mStatus);
+        }
     }
 
     private void dispatchLocations(Location[] locations) {
@@ -275,7 +291,7 @@
             Message message = Message.obtain(
                     entry.getValue(),
                     DispatcherHandler.DISPATCH_LOCATION,
-                    new MessageCommand(entry.getKey(), locations, null /*data*/, 0));
+                    new MessageCommand(entry.getKey(), locations, null /*data*/, 0, 0));
             message.sendToTarget();
         }
     }
@@ -290,7 +306,7 @@
             Message message = Message.obtain(
                     entry.getValue(),
                     DispatcherHandler.DISPATCH_DIAGNOSTIC_DATA,
-                    new MessageCommand(entry.getKey(), null /*locations*/, data, 0));
+                    new MessageCommand(entry.getKey(), null /*locations*/, data, 0, 0));
             message.sendToTarget();
         }
     }
@@ -305,7 +321,22 @@
             Message message = Message.obtain(
                     entry.getValue(),
                     DispatcherHandler.DISPATCH_CAPABILITIES,
-                    new MessageCommand(entry.getKey(), null /*locations*/, null, capabilities));
+                    new MessageCommand(entry.getKey(), null /*locations*/, null, capabilities, 0));
+            message.sendToTarget();
+        }
+    }
+
+    private void dispatchStatus(int status) {
+        HashMap<FusedLocationHardwareSink, DispatcherHandler> sinks;
+        synchronized(mSinkList) {
+            sinks = mSinkList;
+        }
+
+        for(Map.Entry<FusedLocationHardwareSink, DispatcherHandler> entry : sinks.entrySet()) {
+            Message message = Message.obtain(
+                    entry.getValue(),
+                    DispatcherHandler.DISPATCH_STATUS,
+                    new MessageCommand(entry.getKey(), null /*locations*/, null, 0, status));
             message.sendToTarget();
         }
     }
diff --git a/location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java b/location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java
index aaef773..618d5d6 100644
--- a/location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java
+++ b/location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java
@@ -50,4 +50,17 @@
     public void onCapabilities(int capabilities) {
         // default do nothing
     }
+
+    /**
+     * Called when the status changes in the underlying FLP HAL
+     * implementation (the ability to compute location).  This
+     * callback will only be made on API 23 or later.
+     *
+     * @param status One of FLP_STATUS_LOCATION_AVAILABLE or
+     *               FLP_STATUS_LOCATION_UNAVAILABLE as defined in
+     *               fused_location.h.
+     */
+    public void onStatusChanged(int status) {
+        // default do nothing
+    }
 }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/location/FlpHardwareProvider.java b/services/core/java/com/android/server/location/FlpHardwareProvider.java
index 94a1cd8..f41d930 100644
--- a/services/core/java/com/android/server/location/FlpHardwareProvider.java
+++ b/services/core/java/com/android/server/location/FlpHardwareProvider.java
@@ -136,6 +136,20 @@
         maybeSendCapabilities();
     }
 
+    private void onBatchingStatus(int status) {
+        IFusedLocationHardwareSink sink;
+        synchronized (mLocationSinkLock) {
+            sink = mLocationSink;
+        }
+        try {
+            if (sink != null) {
+                sink.onStatusChanged(status);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException calling onBatchingStatus");
+        }
+    }
+
     private void maybeSendCapabilities() {
         IFusedLocationHardwareSink sink;
         boolean haveBatchingCapabilities;
diff --git a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
index 5b5634b..81cdcb0 100644
--- a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
+++ b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
@@ -34,6 +34,7 @@
 static jmethodID sOnLocationReport = NULL;
 static jmethodID sOnDataReport = NULL;
 static jmethodID sOnBatchingCapabilities = NULL;
+static jmethodID sOnBatchingStatus = NULL;
 static jmethodID sOnGeofenceTransition = NULL;
 static jmethodID sOnGeofenceMonitorStatus = NULL;
 static jmethodID sOnGeofenceAdd = NULL;
@@ -100,6 +101,19 @@
   CheckExceptions(sCallbackEnv, __FUNCTION__);
 }
 
+static void BatchingStatusCallback(int32_t status) {
+  if(!IsValidCallbackThread()) {
+    return;
+  }
+
+  sCallbackEnv->CallVoidMethod(
+      sCallbacksObj,
+      sOnBatchingStatus,
+      status
+      );
+  CheckExceptions(sCallbackEnv, __FUNCTION__);
+}
+
 static int SetThreadEvent(ThreadEvent event) {
   JavaVM* javaVm = AndroidRuntime::getJavaVM();
 
@@ -175,6 +189,10 @@
         clazz,
         "onBatchingCapabilities",
         "(I)V");
+    sOnBatchingStatus = env->GetMethodID(
+            clazz,
+            "onBatchingStatus",
+            "(I)V");
     sOnGeofencingCapabilities = env->GetMethodID(
             clazz,
             "onGeofencingCapabilities",
@@ -558,7 +576,8 @@
   AcquireWakelock,
   ReleaseWakelock,
   SetThreadEvent,
-  BatchingCapabilitiesCallback
+  BatchingCapabilitiesCallback,
+  BatchingStatusCallback
 };
 
 static void ReportData(char* data, int length) {