cameraserver: Fix HIDL vs AIDL CameraBlobId discrepancy; Move HIDL into seperate source files.
- Have cameraserver fix the discrepancy between HIDL and AIDL CameraBlobId enum backing type.
- Move HIDL specific code into seperate source files (preparation for b/219020552).
Bug: 219020552
Bug: 229688810
Test: build; use GCA (basic validity)
Test: atest DngCreatorTest.java#testRaw16JpegConsistency (both HIDL and AIDL GCH)
Change-Id: I317c434d22e5e93e7e4cf5ab3aebc4efc93d2d46
Signed-off-by: Jayant Chowdhary <jchowdhary@google.com>
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index c5bdd00..b21322c 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -21,12 +21,16 @@
#include <ctime>
#include <fstream>
+#include <aidl/android/hardware/camera/device/CameraBlob.h>
+#include <aidl/android/hardware/camera/device/CameraBlobId.h>
+
#include <android-base/unique_fd.h>
#include <cutils/properties.h>
#include <ui/GraphicBuffer.h>
#include <utils/Log.h>
#include <utils/Trace.h>
+#include <common/CameraDeviceBase.h>
#include "api1/client2/JpegProcessor.h"
#include "Camera3OutputStream.h"
#include "utils/TraceHFR.h"
@@ -40,12 +44,15 @@
namespace camera3 {
+using aidl::android::hardware::camera::device::CameraBlob;
+using aidl::android::hardware::camera::device::CameraBlobId;
+
Camera3OutputStream::Camera3OutputStream(int id,
sp<Surface> consumer,
uint32_t width, uint32_t height, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
- const std::unordered_set<int32_t> &sensorPixelModesUsed,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed, IPCTransport transport,
int setId, bool isMultiResolution, int64_t dynamicRangeProfile,
int64_t streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
int mirrorMode) :
@@ -62,7 +69,8 @@
mConsumerUsage(0),
mDropBuffers(false),
mMirrorMode(mirrorMode),
- mDequeueBufferLatency(kDequeueLatencyBinSize) {
+ mDequeueBufferLatency(kDequeueLatencyBinSize),
+ mIPCTransport(transport) {
if (mConsumer == NULL) {
ALOGE("%s: Consumer is NULL!", __FUNCTION__);
@@ -78,7 +86,7 @@
uint32_t width, uint32_t height, size_t maxSize, int format,
android_dataspace dataSpace, camera_stream_rotation_t rotation,
nsecs_t timestampOffset, const String8& physicalCameraId,
- const std::unordered_set<int32_t> &sensorPixelModesUsed,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed, IPCTransport transport,
int setId, bool isMultiResolution, int64_t dynamicRangeProfile,
int64_t streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
int mirrorMode) :
@@ -94,7 +102,8 @@
mConsumerUsage(0),
mDropBuffers(false),
mMirrorMode(mirrorMode),
- mDequeueBufferLatency(kDequeueLatencyBinSize) {
+ mDequeueBufferLatency(kDequeueLatencyBinSize),
+ mIPCTransport(transport) {
if (format != HAL_PIXEL_FORMAT_BLOB && format != HAL_PIXEL_FORMAT_RAW_OPAQUE) {
ALOGE("%s: Bad format for size-only stream: %d", __FUNCTION__,
@@ -116,7 +125,7 @@
uint64_t consumerUsage, android_dataspace dataSpace,
camera_stream_rotation_t rotation, nsecs_t timestampOffset,
const String8& physicalCameraId,
- const std::unordered_set<int32_t> &sensorPixelModesUsed,
+ const std::unordered_set<int32_t> &sensorPixelModesUsed, IPCTransport transport,
int setId, bool isMultiResolution, int64_t dynamicRangeProfile,
int64_t streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
int mirrorMode) :
@@ -133,7 +142,8 @@
mConsumerUsage(consumerUsage),
mDropBuffers(false),
mMirrorMode(mirrorMode),
- mDequeueBufferLatency(kDequeueLatencyBinSize) {
+ mDequeueBufferLatency(kDequeueLatencyBinSize),
+ mIPCTransport(transport) {
// Deferred consumer only support preview surface format now.
if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
ALOGE("%s: Deferred consumer only supports IMPLEMENTATION_DEFINED format now!",
@@ -161,6 +171,7 @@
camera_stream_rotation_t rotation,
const String8& physicalCameraId,
const std::unordered_set<int32_t> &sensorPixelModesUsed,
+ IPCTransport transport,
uint64_t consumerUsage, nsecs_t timestampOffset,
int setId, bool isMultiResolution,
int64_t dynamicRangeProfile, int64_t streamUseCase,
@@ -179,7 +190,8 @@
mConsumerUsage(consumerUsage),
mDropBuffers(false),
mMirrorMode(mirrorMode),
- mDequeueBufferLatency(kDequeueLatencyBinSize) {
+ mDequeueBufferLatency(kDequeueLatencyBinSize),
+ mIPCTransport(transport) {
bool needsReleaseNotify = setId > CAMERA3_STREAM_SET_ID_INVALID;
mBufferProducerListener = new BufferProducerListener(this, needsReleaseNotify);
@@ -303,6 +315,73 @@
return OK;
}
+status_t Camera3OutputStream::fixUpHidlJpegBlobHeader(ANativeWindowBuffer* anwBuffer, int fence) {
+ // Lock the JPEG buffer for CPU read
+ sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(anwBuffer);
+ void* mapped = nullptr;
+ base::unique_fd fenceFd(dup(fence));
+ // Use USAGE_SW_WRITE_RARELY since we're going to re-write the CameraBlob
+ // header.
+ GraphicBufferLocker gbLocker(graphicBuffer);
+ status_t res =
+ gbLocker.lockAsync(
+ GraphicBuffer::USAGE_SW_READ_OFTEN | GraphicBuffer::USAGE_SW_WRITE_RARELY,
+ &mapped, fenceFd.get());
+ if (res != OK) {
+ ALOGE("%s: Failed to lock the buffer: %s (%d)", __FUNCTION__, strerror(-res), res);
+ return res;
+ }
+
+ uint8_t *hidlHeaderStart =
+ static_cast<uint8_t*>(mapped) + graphicBuffer->getWidth() - sizeof(camera_jpeg_blob_t);
+ // Check that the jpeg buffer is big enough to contain HIDL camera blob
+ if (hidlHeaderStart < static_cast<uint8_t *>(mapped)) {
+ ALOGE("%s, jpeg buffer not large enough to fit HIDL camera blob %" PRIu32, __FUNCTION__,
+ graphicBuffer->getWidth());
+ return BAD_VALUE;
+ }
+ camera_jpeg_blob_t *hidlBlobHeader = reinterpret_cast<camera_jpeg_blob_t *>(hidlHeaderStart);
+
+ // Check that the blob is indeed the jpeg blob id.
+ if (hidlBlobHeader->jpeg_blob_id != CAMERA_JPEG_BLOB_ID) {
+ ALOGE("%s, jpeg blob id %d is not correct", __FUNCTION__, hidlBlobHeader->jpeg_blob_id);
+ return BAD_VALUE;
+ }
+
+ // Retrieve id and blob size
+ CameraBlobId blobId = static_cast<CameraBlobId>(hidlBlobHeader->jpeg_blob_id);
+ uint32_t blobSizeBytes = hidlBlobHeader->jpeg_size;
+
+ if (blobSizeBytes > (graphicBuffer->getWidth() - sizeof(camera_jpeg_blob_t))) {
+ ALOGE("%s, blobSize in HIDL jpeg blob : %d is corrupt, buffer size %" PRIu32, __FUNCTION__,
+ blobSizeBytes, graphicBuffer->getWidth());
+ }
+
+ uint8_t *aidlHeaderStart =
+ static_cast<uint8_t*>(mapped) + graphicBuffer->getWidth() - sizeof(CameraBlob);
+
+ // Check that the jpeg buffer is big enough to contain AIDL camera blob
+ if (aidlHeaderStart < static_cast<uint8_t *>(mapped)) {
+ ALOGE("%s, jpeg buffer not large enough to fit AIDL camera blob %" PRIu32, __FUNCTION__,
+ graphicBuffer->getWidth());
+ return BAD_VALUE;
+ }
+
+ if (static_cast<uint8_t*>(mapped) + blobSizeBytes > aidlHeaderStart) {
+ ALOGE("%s, jpeg blob with size %d , buffer size %" PRIu32 " not large enough to fit"
+ " AIDL camera blob without corrupting jpeg", __FUNCTION__, blobSizeBytes,
+ graphicBuffer->getWidth());
+ return BAD_VALUE;
+ }
+
+ // Fill in JPEG header
+ CameraBlob *aidlBlobHeader = reinterpret_cast<CameraBlob *>(aidlHeaderStart);
+ aidlBlobHeader->blobId = blobId;
+ aidlBlobHeader->blobSizeBytes = blobSizeBytes;
+ graphicBuffer->unlock();
+ return OK;
+}
+
status_t Camera3OutputStream::returnBufferCheckedLocked(
const camera_stream_buffer &buffer,
nsecs_t timestamp,
@@ -368,12 +447,16 @@
}
mTraceFirstBuffer = false;
}
-
- // If this is a JPEG output, and image dump mask is set, save image to
- // disk.
- if (getFormat() == HAL_PIXEL_FORMAT_BLOB && getDataSpace() == HAL_DATASPACE_V0_JFIF &&
- mImageDumpMask) {
- dumpImageToDisk(timestamp, anwBuffer, anwReleaseFence);
+ // Fix CameraBlob id type discrepancy between HIDL and AIDL, details : http://b/229688810
+ if (getFormat() == HAL_PIXEL_FORMAT_BLOB && getDataSpace() == HAL_DATASPACE_V0_JFIF) {
+ if (mIPCTransport == IPCTransport::HIDL) {
+ fixUpHidlJpegBlobHeader(anwBuffer, anwReleaseFence);
+ }
+ // If this is a JPEG output, and image dump mask is set, save image to
+ // disk.
+ if (mImageDumpMask) {
+ dumpImageToDisk(timestamp, anwBuffer, anwReleaseFence);
+ }
}
if (mPreviewFrameSpacer != nullptr) {