Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d13b1d3 authored by Chien-Yu Chen's avatar Chien-Yu Chen
Browse files

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
parent c5e8b6b7
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
@@ -232,6 +232,14 @@ void Camera::releaseRecordingFrame(const sp<IMemory>& mem)
    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::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<
    }
}

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 @@ void Camera::RecordingProxy::releaseRecordingFrame(const sp<IMemory>& mem)
    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;
+0 −15
Original line number Diff line number Diff line
@@ -122,19 +122,4 @@ status_t CameraUtils::getRotationTransform(const CameraMetadata& staticInfo,
    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 */
+20 −21
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ enum {
    RELEASE_RECORDING_FRAME,
    SET_VIDEO_BUFFER_MODE,
    SET_VIDEO_BUFFER_TARGET,
    RELEASE_RECORDING_FRAME_HANDLE,
};

class BpCamera: public BpInterface<ICamera>
@@ -155,21 +156,20 @@ public:
        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);
    }

        remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
    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);

        if (nh) {
        // Close the native handle because camera received a dup copy.
            native_handle_close(nh);
            native_handle_delete(nh);
        }
        native_handle_close(handle);
        native_handle_delete(handle);
    }

    status_t setVideoBufferMode(int32_t videoBufferMode)
@@ -368,17 +368,16 @@ status_t BnCamera::onTransact(
            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);
+29 −19
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ enum {
    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 @@ public:
        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 @@ status_t BnCameraClient::onTransact(
            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(&timestamp);
            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:
+19 −22
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ enum {
    START_RECORDING = IBinder::FIRST_CALL_TRANSACTION,
    STOP_RECORDING,
    RELEASE_RECORDING_FRAME,
    RELEASE_RECORDING_FRAME_HANDLE,
};


@@ -66,22 +67,20 @@ public:
        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);
    }

        remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
    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);

        if (nh) {
        // Close the native handle because camera received a dup copy.
            native_handle_close(nh);
            native_handle_delete(nh);
        }
        native_handle_close(handle);
        native_handle_delete(handle);
    }
};

@@ -111,19 +110,17 @@ status_t BnCameraRecordingProxy::onTransact(
            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);
    }
Loading