Camera: Fix passing video native handle for 64-bit app
Add new binder calls to pass video native handle so the video native
handle can be passed between 32-bit and 64-bit processes.
Remove problematic code that used IMemory to pass video native
handle because the sizes of VideoNativeMetadata are different in
32-bit and 64-bit processes.
Bug: 28403412
Change-Id: I3341b1812ecc41d61846bb72ca926ecb1674c9ec
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index c52e581..bf9904c 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -232,6 +232,14 @@
c->releaseRecordingFrame(mem);
}
+void Camera::releaseRecordingFrameHandle(native_handle_t* handle)
+{
+ ALOGV("releaseRecordingFrameHandle");
+ sp <::android::hardware::ICamera> c = mCamera;
+ if (c == 0) return;
+ c->releaseRecordingFrameHandle(handle);
+}
+
// get preview state
bool Camera::previewEnabled()
{
@@ -381,6 +389,35 @@
}
}
+void Camera::recordingFrameHandleCallbackTimestamp(nsecs_t timestamp, native_handle_t* handle)
+{
+ // If recording proxy listener is registered, forward the frame and return.
+ // The other listener (mListener) is ignored because the receiver needs to
+ // call releaseRecordingFrameHandle.
+ sp<ICameraRecordingProxyListener> proxylistener;
+ {
+ Mutex::Autolock _l(mLock);
+ proxylistener = mRecordingProxyListener;
+ }
+ if (proxylistener != NULL) {
+ proxylistener->recordingFrameHandleCallbackTimestamp(timestamp, handle);
+ return;
+ }
+
+ sp<CameraListener> listener;
+ {
+ Mutex::Autolock _l(mLock);
+ listener = mListener;
+ }
+
+ if (listener != NULL) {
+ listener->postRecordingFrameHandleTimestamp(timestamp, handle);
+ } else {
+ ALOGW("No listener was set. Drop a recording frame.");
+ releaseRecordingFrameHandle(handle);
+ }
+}
+
sp<ICameraRecordingProxy> Camera::getRecordingProxy() {
ALOGV("getProxy");
return new RecordingProxy(this);
@@ -406,6 +443,11 @@
mCamera->releaseRecordingFrame(mem);
}
+void Camera::RecordingProxy::releaseRecordingFrameHandle(native_handle_t* handle) {
+ ALOGV("RecordingProxy::releaseRecordingFrameHandle");
+ mCamera->releaseRecordingFrameHandle(handle);
+}
+
Camera::RecordingProxy::RecordingProxy(const sp<Camera>& camera)
{
mCamera = camera;
diff --git a/camera/CameraUtils.cpp b/camera/CameraUtils.cpp
index 26eebe3..1676be1 100644
--- a/camera/CameraUtils.cpp
+++ b/camera/CameraUtils.cpp
@@ -122,19 +122,4 @@
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 37b0a10..0680d7c 100644
--- a/camera/ICamera.cpp
+++ b/camera/ICamera.cpp
@@ -54,6 +54,7 @@
RELEASE_RECORDING_FRAME,
SET_VIDEO_BUFFER_MODE,
SET_VIDEO_BUFFER_TARGET,
+ RELEASE_RECORDING_FRAME_HANDLE,
};
class BpCamera: public BpInterface<ICamera>
@@ -155,21 +156,20 @@
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);
- }
+ void releaseRecordingFrameHandle(native_handle_t *handle) {
+ ALOGV("releaseRecordingFrameHandle");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ data.writeNativeHandle(handle);
+
+ remote()->transact(RELEASE_RECORDING_FRAME_HANDLE, data, &reply);
+
+ // Close the native handle because camera received a dup copy.
+ native_handle_close(handle);
+ native_handle_delete(handle);
}
status_t setVideoBufferMode(int32_t videoBufferMode)
@@ -368,17 +368,16 @@
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;
+ case RELEASE_RECORDING_FRAME_HANDLE: {
+ ALOGV("RELEASE_RECORDING_FRAME_HANDLE");
+ CHECK_INTERFACE(ICamera, data, reply);
+ // releaseRecordingFrameHandle will be responsble to close the native handle.
+ releaseRecordingFrameHandle(data.readNativeHandle());
+ return NO_ERROR;
+ } break;
case SET_VIDEO_BUFFER_MODE: {
ALOGV("SET_VIDEO_BUFFER_MODE");
CHECK_INTERFACE(ICamera, data, reply);
diff --git a/camera/ICameraClient.cpp b/camera/ICameraClient.cpp
index d058138..68cbfb8 100644
--- a/camera/ICameraClient.cpp
+++ b/camera/ICameraClient.cpp
@@ -31,6 +31,7 @@
NOTIFY_CALLBACK = IBinder::FIRST_CALL_TRANSACTION,
DATA_CALLBACK,
DATA_CALLBACK_TIMESTAMP,
+ RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP,
};
class BpCameraClient: public BpInterface<ICameraClient>
@@ -78,15 +79,18 @@
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);
}
+
+ void recordingFrameHandleCallbackTimestamp(nsecs_t timestamp, native_handle_t* handle) {
+ ALOGV("recordingFrameHandleCallbackTimestamp");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
+ data.writeInt64(timestamp);
+ data.writeNativeHandle(handle);
+ remote()->transact(RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP, data, &reply,
+ IBinder::FLAG_ONEWAY);
+ }
};
IMPLEMENT_META_INTERFACE(CameraClient, "android.hardware.ICameraClient");
@@ -128,20 +132,26 @@
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;
+ case RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP: {
+ ALOGV("RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP");
+ CHECK_INTERFACE(ICameraClient, data, reply);
+ nsecs_t timestamp;
+ status_t res = data.readInt64(×tamp);
+ if (res != OK) {
+ ALOGE("%s: Failed to read timestamp: %s (%d)", __FUNCTION__, strerror(-res), res);
+ return BAD_VALUE;
+ }
+ native_handle_t* handle = data.readNativeHandle();
+ if (handle == nullptr) {
+ ALOGE("%s: Received a null native handle", __FUNCTION__);
+ return BAD_VALUE;
}
- dataCallbackTimestamp(timestamp, msgType, imageData);
+ // The native handle will be freed in BpCamera::releaseRecordingFrameHandle.
+ recordingFrameHandleCallbackTimestamp(timestamp, handle);
return NO_ERROR;
} break;
default:
diff --git a/camera/ICameraRecordingProxy.cpp b/camera/ICameraRecordingProxy.cpp
index d128f5b..63c4b1d 100644
--- a/camera/ICameraRecordingProxy.cpp
+++ b/camera/ICameraRecordingProxy.cpp
@@ -31,6 +31,7 @@
START_RECORDING = IBinder::FIRST_CALL_TRANSACTION,
STOP_RECORDING,
RELEASE_RECORDING_FRAME,
+ RELEASE_RECORDING_FRAME_HANDLE,
};
@@ -66,22 +67,20 @@
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);
- }
+ void releaseRecordingFrameHandle(native_handle_t *handle) {
+ ALOGV("releaseRecordingFrameHandle");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
+ data.writeNativeHandle(handle);
+
+ remote()->transact(RELEASE_RECORDING_FRAME_HANDLE, data, &reply);
+
+ // Close the native handle because camera received a dup copy.
+ native_handle_close(handle);
+ native_handle_delete(handle);
}
};
@@ -111,19 +110,17 @@
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;
+ case RELEASE_RECORDING_FRAME_HANDLE: {
+ ALOGV("RELEASE_RECORDING_FRAME_HANDLE");
+ CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
+ // releaseRecordingFrameHandle will be responsble to close the native handle.
+ releaseRecordingFrameHandle(data.readNativeHandle());
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/camera/ICameraRecordingProxyListener.cpp b/camera/ICameraRecordingProxyListener.cpp
index 447174e..fa4dfd8 100644
--- a/camera/ICameraRecordingProxyListener.cpp
+++ b/camera/ICameraRecordingProxyListener.cpp
@@ -27,6 +27,7 @@
enum {
DATA_CALLBACK_TIMESTAMP = IBinder::FIRST_CALL_TRANSACTION,
+ RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP,
};
class BpCameraRecordingProxyListener: public BpInterface<ICameraRecordingProxyListener>
@@ -45,22 +46,21 @@
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);
+ }
+
+ void recordingFrameHandleCallbackTimestamp(nsecs_t timestamp, native_handle_t* handle) {
+ ALOGV("recordingFrameHandleCallbackTimestamp");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraRecordingProxyListener::getInterfaceDescriptor());
+ data.writeInt64(timestamp);
+ data.writeNativeHandle(handle);
+ remote()->transact(RECORDING_FRAME_HANDLE_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);
- }
+ native_handle_close(handle);
+ native_handle_delete(handle);
}
};
@@ -78,16 +78,27 @@
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;
+ case RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP: {
+ ALOGV("RECORDING_FRAME_HANDLE_CALLBACK_TIMESTAMP");
+ CHECK_INTERFACE(ICameraRecordingProxyListener, data, reply);
+ nsecs_t timestamp;
+ status_t res = data.readInt64(×tamp);
+ if (res != OK) {
+ ALOGE("%s: Failed to read timestamp: %s (%d)", __FUNCTION__, strerror(-res), res);
+ return BAD_VALUE;
}
- dataCallbackTimestamp(timestamp, msgType, imageData);
+ native_handle_t* handle = data.readNativeHandle();
+ if (handle == nullptr) {
+ ALOGE("%s: Received a null native handle", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ // The native handle will be freed in
+ // BpCameraRecordingProxy::releaseRecordingFrameHandle.
+ recordingFrameHandleCallbackTimestamp(timestamp, handle);
return NO_ERROR;
} break;
default: