Camera: Combine handling of deferred surface and shared surface

- Refactor the OutputConfiguration to contain isDeferred and isShared
  flag, and not contain NULL surface.
- Unify the handling of deferred surface and shared surface.

Test: Camera CTS, and manual testing of GoogleCamera use cases
Bug: 33777818
Change-Id: I5dd3472f0f2133699b0e9fbdd8ba456956222746
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index 9cd3a47..f570b7f 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -56,12 +56,22 @@
     return mHeight;
 }
 
+bool OutputConfiguration::isDeferred() const {
+    return mIsDeferred;
+}
+
+bool OutputConfiguration::isShared() const {
+    return mIsShared;
+}
+
 OutputConfiguration::OutputConfiguration() :
         mRotation(INVALID_ROTATION),
         mSurfaceSetID(INVALID_SET_ID),
         mSurfaceType(SURFACE_TYPE_UNKNOWN),
         mWidth(0),
-        mHeight(0) {
+        mHeight(0),
+        mIsDeferred(false),
+        mIsShared(false) {
 }
 
 OutputConfiguration::OutputConfiguration(const android::Parcel& parcel) :
@@ -105,42 +115,28 @@
         return err;
     }
 
-    // numSurfaces is the total number of surfaces for this OutputConfiguration,
-    // regardless the surface is deferred or not.
-    int numSurfaces = 0;
-    if ((err = parcel->readInt32(&numSurfaces)) != OK) {
-        ALOGE("%s: Failed to read maxSurfaces from parcel", __FUNCTION__);
+    int isDeferred = 0;
+    if ((err = parcel->readInt32(&isDeferred)) != OK) {
+        ALOGE("%s: Failed to read surface isDeferred flag from parcel", __FUNCTION__);
         return err;
     }
-    if (numSurfaces < 1) {
-        ALOGE("%s: there has to be at least 1 surface per"
-              " outputConfiguration", __FUNCTION__);
+
+    int isShared = 0;
+    if ((err = parcel->readInt32(&isShared)) != OK) {
+        ALOGE("%s: Failed to read surface isShared flag from parcel", __FUNCTION__);
+        return err;
+    }
+
+    if (isDeferred && surfaceType != SURFACE_TYPE_SURFACE_VIEW &&
+            surfaceType != SURFACE_TYPE_SURFACE_TEXTURE) {
+        ALOGE("%s: Invalid surface type for deferred configuration", __FUNCTION__);
         return BAD_VALUE;
     }
 
-    // Read all surfaces from parcel. If a surface is deferred, readFromPacel
-    // returns error, and a null surface is put into the mGbps. We assume all
-    // deferred surfaces are after non-deferred surfaces in the parcel.
-    // TODO: Need better way to detect deferred surface than using error
-    // return from readFromParcel.
-    std::vector<sp<IGraphicBufferProducer>> gbps;
-    for (int i = 0; i < numSurfaces; i++) {
-        view::Surface surfaceShim;
-        if ((err = surfaceShim.readFromParcel(parcel)) != OK) {
-            // Read surface failure for deferred surface configuration is expected.
-            if ((surfaceType == SURFACE_TYPE_SURFACE_VIEW ||
-                    surfaceType == SURFACE_TYPE_SURFACE_TEXTURE)) {
-                ALOGV("%s: Get null surface from a deferred surface configuration (%dx%d)",
-                        __FUNCTION__, width, height);
-                err = OK;
-            } else {
-                ALOGE("%s: Failed to read surface from parcel", __FUNCTION__);
-                return err;
-            }
-        }
-        gbps.push_back(surfaceShim.graphicBufferProducer);
-        ALOGV("%s: OutputConfiguration: gbps[%d] : %p, name %s", __FUNCTION__,
-                i, gbps[i].get(), String8(surfaceShim.name).string());
+    std::vector<view::Surface> surfaceShims;
+    if ((err = parcel->readParcelableVector(&surfaceShims)) != OK) {
+        ALOGE("%s: Failed to read surface(s) from parcel", __FUNCTION__);
+        return err;
     }
 
     mRotation = rotation;
@@ -148,7 +144,14 @@
     mSurfaceType = surfaceType;
     mWidth = width;
     mHeight = height;
-    mGbps = std::move(gbps);
+    mIsDeferred = isDeferred != 0;
+    mIsShared = isShared != 0;
+    for (auto& surface : surfaceShims) {
+        ALOGV("%s: OutputConfiguration: %p, name %s", __FUNCTION__,
+                surface.graphicBufferProducer.get(),
+                String8(surface.name).string());
+        mGbps.push_back(surface.graphicBufferProducer);
+    }
 
     ALOGV("%s: OutputConfiguration: rotation = %d, setId = %d, surfaceType = %d",
             __FUNCTION__, mRotation, mSurfaceSetID, mSurfaceType);
@@ -161,6 +164,8 @@
     mGbps.push_back(gbp);
     mRotation = rotation;
     mSurfaceSetID = surfaceSetID;
+    mIsDeferred = false;
+    mIsShared = false;
 }
 
 status_t OutputConfiguration::writeToParcel(android::Parcel* parcel) const {
@@ -183,18 +188,21 @@
     err = parcel->writeInt32(mHeight);
     if (err != OK) return err;
 
-    int numSurfaces = mGbps.size();
-    err = parcel->writeInt32(numSurfaces);
+    err = parcel->writeInt32(mIsDeferred ? 1 : 0);
     if (err != OK) return err;
 
-    for (int i = 0; i < numSurfaces; i++) {
+    err = parcel->writeInt32(mIsShared ? 1 : 0);
+    if (err != OK) return err;
+
+    std::vector<view::Surface> surfaceShims;
+    for (auto& gbp : mGbps) {
         view::Surface surfaceShim;
         surfaceShim.name = String16("unknown_name"); // name of surface
-        surfaceShim.graphicBufferProducer = mGbps[i];
-
-        err = surfaceShim.writeToParcel(parcel);
-        if (err != OK) return err;
+        surfaceShim.graphicBufferProducer = gbp;
+        surfaceShims.push_back(surfaceShim);
     }
+    err = parcel->writeParcelableVector(surfaceShims);
+    if (err != OK) return err;
 
     return OK;
 }