camera: Add support to pass native handles across binders

If the video buffer contains a native handle, serialize and
deserialize it properly.

Author: spodder@codeaurora.org
Bug: 26268807
Change-Id: I1905be81e2045667e00c95ab75d1bf144756b894
diff --git a/camera/Android.mk b/camera/Android.mk
index 471cb0d..de23953 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -52,6 +52,7 @@
 LOCAL_C_INCLUDES += \
 	system/media/camera/include \
 	system/media/private/camera/include \
+	frameworks/native/include/media/openmax \
 
 LOCAL_MODULE:= libcamera_client
 
diff --git a/camera/CameraUtils.cpp b/camera/CameraUtils.cpp
index 04244ac..26eebe3 100644
--- a/camera/CameraUtils.cpp
+++ b/camera/CameraUtils.cpp
@@ -18,6 +18,7 @@
 //#define LOG_NDEBUG 0
 
 #include <camera/CameraUtils.h>
+#include <media/hardware/HardwareAPI.h>
 
 #include <system/window.h>
 #include <system/graphics.h>
@@ -121,5 +122,19 @@
     return OK;
 }
 
+// Return whether the image data contains a native handle.
+bool CameraUtils::isNativeHandleMetadata(const sp<IMemory>& imageData) {
+    if (imageData == nullptr) {
+        return false;
+    }
+
+    if (imageData->size() == sizeof(VideoNativeHandleMetadata)) {
+        VideoNativeHandleMetadata *metadata =
+                (VideoNativeHandleMetadata*)(imageData->pointer());
+        return metadata->eType == kMetadataBufferTypeNativeHandleSource;
+    }
+
+    return false;
+}
 
 } /* namespace android */
diff --git a/camera/ICamera.cpp b/camera/ICamera.cpp
index cce5a9a..1dd8912 100644
--- a/camera/ICamera.cpp
+++ b/camera/ICamera.cpp
@@ -21,9 +21,11 @@
 #include <stdint.h>
 #include <sys/types.h>
 #include <binder/Parcel.h>
+#include <camera/CameraUtils.h>
 #include <camera/ICamera.h>
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/Surface.h>
+#include <media/hardware/HardwareAPI.h>
 
 namespace android {
 
@@ -149,7 +151,22 @@
         Parcel data, reply;
         data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
         data.writeStrongBinder(IInterface::asBinder(mem));
+
+        native_handle_t *nh = nullptr;
+        if (CameraUtils::isNativeHandleMetadata(mem)) {
+            VideoNativeHandleMetadata *metadata =
+                        (VideoNativeHandleMetadata*)(mem->pointer());
+            nh = metadata->pHandle;
+            data.writeNativeHandle(nh);
+        }
+
         remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
+
+        if (nh) {
+            // Close the native handle because camera received a dup copy.
+            native_handle_close(nh);
+            native_handle_delete(nh);
+        }
     }
 
     status_t setVideoBufferMode(int32_t videoBufferMode)
@@ -348,6 +365,14 @@
             ALOGV("RELEASE_RECORDING_FRAME");
             CHECK_INTERFACE(ICamera, data, reply);
             sp<IMemory> mem = interface_cast<IMemory>(data.readStrongBinder());
+
+            if (CameraUtils::isNativeHandleMetadata(mem)) {
+                VideoNativeHandleMetadata *metadata =
+                        (VideoNativeHandleMetadata*)(mem->pointer());
+                metadata->pHandle = data.readNativeHandle();
+                // releaseRecordingFrame will be responsble to close the native handle.
+            }
+
             releaseRecordingFrame(mem);
             return NO_ERROR;
         } break;
diff --git a/camera/ICameraClient.cpp b/camera/ICameraClient.cpp
index 179a341..4282f9a 100644
--- a/camera/ICameraClient.cpp
+++ b/camera/ICameraClient.cpp
@@ -2,16 +2,16 @@
 **
 ** Copyright 2008, 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 
+** 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 
+**     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 
+** 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.
 */
 
@@ -20,7 +20,9 @@
 #include <utils/Log.h>
 #include <stdint.h>
 #include <sys/types.h>
+#include <camera/CameraUtils.h>
 #include <camera/ICameraClient.h>
+#include <media/hardware/HardwareAPI.h>
 
 namespace android {
 
@@ -75,6 +77,13 @@
         data.writeInt64(timestamp);
         data.writeInt32(msgType);
         data.writeStrongBinder(IInterface::asBinder(imageData));
+        // If imageData is metadata and it contains a native handle, write the native handle to
+        // parcel.
+        if (CameraUtils::isNativeHandleMetadata(imageData)) {
+            VideoNativeHandleMetadata *metadata =
+                    (VideoNativeHandleMetadata*)(imageData->pointer());
+            data.writeNativeHandle(metadata->pHandle);
+        }
         remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY);
     }
 };
@@ -118,6 +127,19 @@
             nsecs_t timestamp = data.readInt64();
             int32_t msgType = data.readInt32();
             sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
+
+            // If the image data contains a native handle, read the native handle from the parcel
+            // and replace the native handle in the image data. (The native handle in image data is
+            // not serielized/deserialized so it's not valid in the process.)
+            if (CameraUtils::isNativeHandleMetadata(imageData)) {
+                VideoNativeHandleMetadata *metadata =
+                        (VideoNativeHandleMetadata*)(imageData->pointer());
+                metadata->pHandle = data.readNativeHandle();
+
+                // The native handle will be freed in
+                // BpCameraRecordingProxyListener::releaseRecordingFrame.
+            }
+
             dataCallbackTimestamp(timestamp, msgType, imageData);
             return NO_ERROR;
         } break;
diff --git a/camera/ICameraRecordingProxy.cpp b/camera/ICameraRecordingProxy.cpp
index 3dc0ffb..d128f5b 100644
--- a/camera/ICameraRecordingProxy.cpp
+++ b/camera/ICameraRecordingProxy.cpp
@@ -16,10 +16,12 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "ICameraRecordingProxy"
+#include <camera/CameraUtils.h>
 #include <camera/ICameraRecordingProxy.h>
 #include <camera/ICameraRecordingProxyListener.h>
 #include <binder/IMemory.h>
 #include <binder/Parcel.h>
+#include <media/hardware/HardwareAPI.h>
 #include <stdint.h>
 #include <utils/Log.h>
 
@@ -64,7 +66,22 @@
         Parcel data, reply;
         data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
         data.writeStrongBinder(IInterface::asBinder(mem));
+
+        native_handle_t *nh = nullptr;
+        if (CameraUtils::isNativeHandleMetadata(mem)) {
+            VideoNativeHandleMetadata *metadata =
+                        (VideoNativeHandleMetadata*)(mem->pointer());
+            nh = metadata->pHandle;
+            data.writeNativeHandle(nh);
+        }
+
         remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
+
+        if (nh) {
+            // Close the native handle because camera received a dup copy.
+            native_handle_close(nh);
+            native_handle_delete(nh);
+        }
     }
 };
 
@@ -94,7 +111,16 @@
             ALOGV("RELEASE_RECORDING_FRAME");
             CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
             sp<IMemory> mem = interface_cast<IMemory>(data.readStrongBinder());
+
+            if (CameraUtils::isNativeHandleMetadata(mem)) {
+                VideoNativeHandleMetadata *metadata =
+                        (VideoNativeHandleMetadata*)(mem->pointer());
+                metadata->pHandle = data.readNativeHandle();
+
+                // releaseRecordingFrame will be responsble to close the native handle.
+            }
             releaseRecordingFrame(mem);
+
             return NO_ERROR;
         } break;
 
diff --git a/camera/ICameraRecordingProxyListener.cpp b/camera/ICameraRecordingProxyListener.cpp
index cf848fc..447174e 100644
--- a/camera/ICameraRecordingProxyListener.cpp
+++ b/camera/ICameraRecordingProxyListener.cpp
@@ -16,9 +16,11 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "ICameraRecordingProxyListener"
+#include <camera/CameraUtils.h>
 #include <camera/ICameraRecordingProxyListener.h>
 #include <binder/IMemory.h>
 #include <binder/Parcel.h>
+#include <media/hardware/HardwareAPI.h>
 #include <utils/Log.h>
 
 namespace android {
@@ -43,7 +45,22 @@
         data.writeInt64(timestamp);
         data.writeInt32(msgType);
         data.writeStrongBinder(IInterface::asBinder(imageData));
+        native_handle_t* nh = nullptr;
+
+        if (CameraUtils::isNativeHandleMetadata(imageData)) {
+            VideoNativeHandleMetadata *metadata =
+                    (VideoNativeHandleMetadata*)(imageData->pointer());
+            nh = metadata->pHandle;
+            data.writeNativeHandle(nh);
+        }
+
         remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY);
+
+        // The native handle is dupped in ICameraClient so we need to free it here.
+        if (nh) {
+            native_handle_close(nh);
+            native_handle_delete(nh);
+        }
     }
 };
 
@@ -61,6 +78,15 @@
             nsecs_t timestamp = data.readInt64();
             int32_t msgType = data.readInt32();
             sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
+
+            if (CameraUtils::isNativeHandleMetadata(imageData)) {
+                VideoNativeHandleMetadata *meta = (VideoNativeHandleMetadata*)(imageData->pointer());
+                meta->pHandle = data.readNativeHandle();
+
+                // The native handle will be freed in
+                // BpCameraRecordingProxyListener::releaseRecordingFrame.
+            }
+
             dataCallbackTimestamp(timestamp, msgType, imageData);
             return NO_ERROR;
         } break;