Camera API2: Add support for partial result quirk

- Camera3Device: Include requestId in partial 3A results
- FrameProcessorBase: Add support for partial result listeners
- CameraDeviceClient: Listen and forward partial results to client

Bug: 11115603
Change-Id: If1cc6bbc32932742ac142c058688761ebf6a8024
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 72126c1..1cdf8dc 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -81,7 +81,8 @@
 
     mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID,
                                       FRAME_PROCESSOR_LISTENER_MAX_ID,
-                                      /*listener*/this);
+                                      /*listener*/this,
+                                      /*quirkSendPartials*/true);
 
     return OK;
 }
diff --git a/services/camera/libcameraservice/common/FrameProcessorBase.cpp b/services/camera/libcameraservice/common/FrameProcessorBase.cpp
index b2c9b33..f2064fb 100644
--- a/services/camera/libcameraservice/common/FrameProcessorBase.cpp
+++ b/services/camera/libcameraservice/common/FrameProcessorBase.cpp
@@ -37,11 +37,11 @@
 }
 
 status_t FrameProcessorBase::registerListener(int32_t minId,
-        int32_t maxId, wp<FilteredListener> listener) {
+        int32_t maxId, wp<FilteredListener> listener, bool quirkSendPartials) {
     Mutex::Autolock l(mInputMutex);
     ALOGV("%s: Registering listener for frame id range %d - %d",
             __FUNCTION__, minId, maxId);
-    RangeListener rListener = { minId, maxId, listener };
+    RangeListener rListener = { minId, maxId, listener, quirkSendPartials };
     mRangeListeners.push_back(rListener);
     return OK;
 }
@@ -145,13 +145,14 @@
     ATRACE_CALL();
     camera_metadata_ro_entry_t entry;
 
-    // Quirks: Don't deliver partial results to listeners
+    // Quirks: Don't deliver partial results to listeners that don't want them
+    bool quirkIsPartial = false;
     entry = frame.find(ANDROID_QUIRKS_PARTIAL_RESULT);
     if (entry.count != 0 &&
             entry.data.u8[0] == ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL) {
         ALOGV("%s: Camera %d: Not forwarding partial result to listeners",
                 __FUNCTION__, device->getId());
-        return OK;
+        quirkIsPartial = true;
     }
 
     entry = frame.find(ANDROID_REQUEST_ID);
@@ -169,7 +170,8 @@
         List<RangeListener>::iterator item = mRangeListeners.begin();
         while (item != mRangeListeners.end()) {
             if (requestId >= item->minId &&
-                    requestId < item->maxId) {
+                    requestId < item->maxId &&
+                    (!quirkIsPartial || item->quirkSendPartials) ) {
                 sp<FilteredListener> listener = item->listener.promote();
                 if (listener == 0) {
                     item = mRangeListeners.erase(item);
diff --git a/services/camera/libcameraservice/common/FrameProcessorBase.h b/services/camera/libcameraservice/common/FrameProcessorBase.h
index 4d80ebf..89b608a 100644
--- a/services/camera/libcameraservice/common/FrameProcessorBase.h
+++ b/services/camera/libcameraservice/common/FrameProcessorBase.h
@@ -44,9 +44,11 @@
     };
 
     // Register a listener for a range of IDs [minId, maxId). Multiple listeners
-    // can be listening to the same range
+    // can be listening to the same range.
+    // QUIRK: sendPartials controls whether partial results will be sent.
     status_t registerListener(int32_t minId, int32_t maxId,
-                              wp<FilteredListener> listener);
+                              wp<FilteredListener> listener,
+                              bool quirkSendPartials = true);
     status_t removeListener(int32_t minId, int32_t maxId,
                             wp<FilteredListener> listener);
 
@@ -64,6 +66,7 @@
         int32_t minId;
         int32_t maxId;
         wp<FilteredListener> listener;
+        bool quirkSendPartials;
     };
     List<RangeListener> mRangeListeners;
 
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index cb72e0e..3dbc1b0 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1405,7 +1405,8 @@
  * Check if all 3A fields are ready, and send off a partial 3A-only result
  * to the output frame queue
  */
-bool Camera3Device::processPartial3AQuirk(int32_t frameNumber,
+bool Camera3Device::processPartial3AQuirk(
+        int32_t frameNumber, int32_t requestId,
         const CameraMetadata& partial) {
 
     // Check if all 3A states are present
@@ -1452,10 +1453,10 @@
 
     if (!gotAllStates) return false;
 
-    ALOGVV("%s: Camera %d: Frame %d: AF mode %d, AWB mode %d, "
+    ALOGVV("%s: Camera %d: Frame %d, Request ID %d: AF mode %d, AWB mode %d, "
         "AF state %d, AE state %d, AWB state %d, "
         "AF trigger %d, AE precapture trigger %d",
-        __FUNCTION__, mId, frameNumber,
+        __FUNCTION__, mId, frameNumber, requestId,
         afMode, awbMode,
         afState, aeState, awbState,
         afTriggerId, aeTriggerId);
@@ -1463,9 +1464,10 @@
     // Got all states, so construct a minimal result to send
     // In addition to the above fields, this means adding in
     //   android.request.frameCount
+    //   android.request.requestId
     //   android.quirks.partialResult
 
-    const size_t kMinimal3AResultEntries = 7;
+    const size_t kMinimal3AResultEntries = 10;
 
     Mutex::Autolock l(mOutputLock);
 
@@ -1479,6 +1481,11 @@
         return false;
     }
 
+    if (!insert3AResult(min3AResult, ANDROID_REQUEST_ID,
+            &requestId, frameNumber)) {
+        return false;
+    }
+
     static const uint8_t partialResult = ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL;
     if (!insert3AResult(min3AResult, ANDROID_QUIRKS_PARTIAL_RESULT,
             &partialResult, frameNumber)) {
@@ -1615,7 +1622,8 @@
                 if (!request.partialResultQuirk.haveSent3A) {
                     request.partialResultQuirk.haveSent3A =
                             processPartial3AQuirk(frameNumber,
-                                request.partialResultQuirk.collectedResult);
+                                    request.requestId,
+                                    request.partialResultQuirk.collectedResult);
                 }
             }
         }
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 4a24a88..468f641 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -491,7 +491,8 @@
      * and if so, queue up 3A-only result to the client. Returns true if 3A
      * is sent.
      */
-    bool processPartial3AQuirk(int32_t frameNumber, const CameraMetadata& partial);
+    bool processPartial3AQuirk(int32_t frameNumber, int32_t requestId,
+            const CameraMetadata& partial);
 
     // Helpers for reading and writing 3A metadata into to/from partial results
     template<typename T>