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

Commit 08dd245c authored by Emilian Peev's avatar Emilian Peev
Browse files

Camera: Make device related code version agnostic

Camera device related code should be agnostic w.r.t.
device version as much as possible. Specifically the
following requirements must hold true:
- Since support for devices 3.0&3.1 is deprecated
"ANDROID_QUIRKS_USE_PARTIAL_RESULT" is no longer considered.
- "ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS" is always
used instead of the deprecated "ANDROID_SCALER_AVAILABLE_JPEG_SIZES".
- Buffer manager for camera streams is used for dynamic buffer
allocation.
- "flush" is always used instead of waiting for buffers to drain.
- Similar to "flush" stream "tearDown" is always available.
- Dead code handling buffer registration is removed.

Bug: 34392075
Test: Manual using camera application
Change-Id: If1b215f785ba61c6991fdf163d4eb18733690471
parent 94cfe137
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -306,11 +306,6 @@ class CameraDeviceBase : public virtual RefBase {
     */
    virtual status_t prepare(int maxCount, int streamId) = 0;

    /**
     * Get the HAL device version.
     */
    virtual uint32_t getDeviceVersion() = 0;

    /**
     * Set the deferred consumer surface and finish the rest of the stream configuration.
     */
+3 −14
Original line number Diff line number Diff line
@@ -32,8 +32,7 @@ FrameProcessorBase::FrameProcessorBase(wp<CameraDeviceBase> device) :
    mDevice(device),
    mNumPartialResults(1) {
    sp<CameraDeviceBase> cameraDevice = device.promote();
    if (cameraDevice != 0 &&
            cameraDevice->getDeviceVersion() >= CAMERA_DEVICE_API_VERSION_3_2) {
    if (cameraDevice != 0) {
        CameraMetadata staticInfo = cameraDevice->info();
        camera_metadata_entry_t entry = staticInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
        if (entry.count > 0) {
@@ -171,18 +170,8 @@ status_t FrameProcessorBase::processListeners(const CaptureResult &result,
    camera_metadata_ro_entry_t entry;

    // Check if this result is partial.
    bool isPartialResult = false;
    if (device->getDeviceVersion() >= CAMERA_DEVICE_API_VERSION_3_2) {
        isPartialResult = result.mResultExtras.partialResultCount < mNumPartialResults;
    } else {
        entry = result.mMetadata.find(ANDROID_QUIRKS_PARTIAL_RESULT);
        if (entry.count != 0 &&
                entry.data.u8[0] == ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL) {
            ALOGV("%s: Camera %s: This is a partial result",
                    __FUNCTION__, device->getId().string());
            isPartialResult = true;
        }
    }
    bool isPartialResult =
            result.mResultExtras.partialResultCount < mNumPartialResults;

    // TODO: instead of getting requestID from CameraMetadata, we should get it
    // from CaptureResultExtras. This will require changing Camera2Device.
+41 −160
Original line number Diff line number Diff line
@@ -306,20 +306,12 @@ status_t Camera3Device::initializeCommonLocked() {
    }

    // Will the HAL be sending in early partial result metadata?
    if (mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_2) {
    camera_metadata_entry partialResultsCount =
            mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
    if (partialResultsCount.count > 0) {
        mNumPartialResults = partialResultsCount.data.i32[0];
        mUsePartialResult = (mNumPartialResults > 1);
    }
    } else {
        camera_metadata_entry partialResultsQuirk =
                mDeviceInfo.find(ANDROID_QUIRKS_USE_PARTIAL_RESULT);
        if (partialResultsQuirk.count > 0 && partialResultsQuirk.data.u8[0] == 1) {
            mUsePartialResult = true;
        }
    }

    camera_metadata_entry configs =
            mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
@@ -434,7 +426,6 @@ bool Camera3Device::tryLockSpinRightRound(Mutex& lock) {

Camera3Device::Size Camera3Device::getMaxJpegResolution() const {
    int32_t maxJpegWidth = 0, maxJpegHeight = 0;
    if (mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_2) {
    const int STREAM_CONFIGURATION_SIZE = 4;
    const int STREAM_FORMAT_OFFSET = 0;
    const int STREAM_WIDTH_OFFSET = 1;
@@ -460,22 +451,7 @@ Camera3Device::Size Camera3Device::getMaxJpegResolution() const {
            maxJpegHeight = height;
        }
    }
    } else {
        camera_metadata_ro_entry availableJpegSizes =
                mDeviceInfo.find(ANDROID_SCALER_AVAILABLE_JPEG_SIZES);
        if (availableJpegSizes.count == 0 || availableJpegSizes.count % 2 != 0) {
            return Size(0, 0);
        }

        // Get max jpeg size (area-wise).
        for (size_t i = 0; i < availableJpegSizes.count; i += 2) {
            if ((availableJpegSizes.data.i32[i] * availableJpegSizes.data.i32[i + 1])
                    > (maxJpegWidth * maxJpegHeight)) {
                maxJpegWidth = availableJpegSizes.data.i32[i];
                maxJpegHeight = availableJpegSizes.data.i32[i + 1];
            }
        }
    }
    return Size(maxJpegWidth, maxJpegHeight);
}

@@ -497,31 +473,6 @@ nsecs_t Camera3Device::getMonoToBoottimeOffset() {
    return measured;
}

/**
 * Map Android N dataspace definitions back to Android M definitions, for
 * use with HALv3.3 or older.
 *
 * Only map where correspondences exist, and otherwise preserve the value.
 */
android_dataspace Camera3Device::mapToLegacyDataspace(android_dataspace dataSpace) {
    switch (dataSpace) {
        case HAL_DATASPACE_V0_SRGB_LINEAR:
            return HAL_DATASPACE_SRGB_LINEAR;
        case HAL_DATASPACE_V0_SRGB:
            return HAL_DATASPACE_SRGB;
        case HAL_DATASPACE_V0_JFIF:
            return HAL_DATASPACE_JFIF;
        case HAL_DATASPACE_V0_BT601_625:
            return HAL_DATASPACE_BT601_625;
        case HAL_DATASPACE_V0_BT601_525:
            return HAL_DATASPACE_BT601_525;
        case HAL_DATASPACE_V0_BT709:
            return HAL_DATASPACE_BT709;
        default:
            return dataSpace;
    }
}

hardware::graphics::common::V1_0::PixelFormat Camera3Device::mapToPixelFormat(
        int frameworkFormat) {
    return (hardware::graphics::common::V1_0::PixelFormat) frameworkFormat;
@@ -1365,32 +1316,17 @@ status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
    assert(mStatus != STATUS_ACTIVE);

    sp<Camera3OutputStream> newStream;
    // Overwrite stream set id to invalid for HAL3.2 or lower, as buffer manager does support
    // such devices.
    if (mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_2) {
        streamSetId = CAMERA3_STREAM_SET_ID_INVALID;
    }

    if (consumers.size() == 0 && !hasDeferredConsumer) {
        ALOGE("%s: Number of consumers cannot be smaller than 1", __FUNCTION__);
        return BAD_VALUE;
    }
    // HAL3.1 doesn't support deferred consumer stream creation as it requires buffer registration
    // which requires a consumer surface to be available.
    if (hasDeferredConsumer && mDeviceVersion < CAMERA_DEVICE_API_VERSION_3_2) {
        ALOGE("HAL3.1 doesn't support deferred consumer stream creation");
        return BAD_VALUE;
    }

    if (hasDeferredConsumer && format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
        ALOGE("Deferred consumer stream creation only support IMPLEMENTATION_DEFINED format");
        return BAD_VALUE;
    }

    // Use legacy dataspace values for older HALs
    if (mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_3) {
        dataSpace = mapToLegacyDataspace(dataSpace);
    }
    if (format == HAL_PIXEL_FORMAT_BLOB) {
        ssize_t blobBufferSize;
        if (dataSpace != HAL_DATASPACE_DEPTH) {
@@ -1433,15 +1369,7 @@ status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
    }
    newStream->setStatusTracker(mStatusTracker);

    /**
     * Camera3 Buffer manager is only supported by HAL3.3 onwards, as the older HALs ( < HAL3.2)
     * requires buffers to be statically allocated for internal static buffer registration, while
     * the buffers provided by buffer manager are really dynamically allocated. For HAL3.2, because
     * not all HAL implementation supports dynamic buffer registeration, exlude it as well.
     */
    if (mDeviceVersion > CAMERA_DEVICE_API_VERSION_3_2) {
    newStream->setBufferManager(mBufferManager);
    }

    res = mOutputStreams.add(mNextStreamId, newStream);
    if (res < 0) {
@@ -1919,15 +1847,7 @@ status_t Camera3Device::flush(int64_t *frameNumber) {
        mRequestThread->clear(/*out*/frameNumber);
    }

    status_t res;
    if (mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_1) {
        res = mRequestThread->flush();
    } else {
        Mutex::Autolock l(mLock);
        res = waitUntilDrainedLocked();
    }

    return res;
    return mRequestThread->flush();
}

status_t Camera3Device::prepare(int streamId) {
@@ -1968,14 +1888,6 @@ status_t Camera3Device::tearDown(int streamId) {
    Mutex::Autolock il(mInterfaceLock);
    Mutex::Autolock l(mLock);

    // Teardown can only be accomplished on devices that don't require register_stream_buffers,
    // since we cannot call register_stream_buffers except right after configure_streams.
    if (mDeviceVersion < CAMERA_DEVICE_API_VERSION_3_2) {
        ALOGE("%s: Unable to tear down streams on device HAL v%x",
                __FUNCTION__, mDeviceVersion);
        return NO_INIT;
    }

    sp<Camera3StreamInterface> stream;
    ssize_t outputStreamIdx = mOutputStreams.indexOfKey(streamId);
    if (outputStreamIdx == NAME_NOT_FOUND) {
@@ -2013,12 +1925,6 @@ status_t Camera3Device::addBufferListenerForStream(int streamId,
    return OK;
}

uint32_t Camera3Device::getDeviceVersion() {
    ATRACE_CALL();
    Mutex::Autolock il(mInterfaceLock);
    return mDeviceVersion;
}

/**
 * Methods called by subclasses
 */
@@ -2732,10 +2638,7 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
        return;
    }

    // For HAL3.2 or above, If HAL doesn't support partial, it must always set
    // partial_result to 1 when metadata is included in this result.
    if (!mUsePartialResult &&
            mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_2 &&
            result->result != NULL &&
            result->partial_result != 1) {
        SET_ERR("Result is malformed for frame %d: partial_result %u must be 1"
@@ -2780,7 +2683,6 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {

        // Check if this result carries only partial metadata
        if (mUsePartialResult && result->result != NULL) {
            if (mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_2) {
            if (result->partial_result > mNumPartialResults || result->partial_result < 1) {
                SET_ERR("Result is malformed for frame %d: partial_result %u must be  in"
                        " the range of [1, %d] when metadata is included in the result",
@@ -2791,23 +2693,6 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
            if (isPartialResult) {
                request.collectedPartialResult.append(result->result);
            }
            } else {
                camera_metadata_ro_entry_t partialResultEntry;
                res = find_camera_metadata_ro_entry(result->result,
                        ANDROID_QUIRKS_PARTIAL_RESULT, &partialResultEntry);
                if (res != NAME_NOT_FOUND &&
                        partialResultEntry.count > 0 &&
                        partialResultEntry.data.u8[0] ==
                        ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL) {
                    // A partial result. Flag this as such, and collect this
                    // set of metadata into the in-flight entry.
                    isPartialResult = true;
                    request.collectedPartialResult.append(
                        result->result);
                    request.collectedPartialResult.erase(
                        ANDROID_QUIRKS_PARTIAL_RESULT);
                }
            }

            if (isPartialResult && request.hasCallback) {
                // Send partial capture result
@@ -3820,13 +3705,9 @@ status_t Camera3Device::RequestThread::flush() {
    ATRACE_CALL();
    Mutex::Autolock l(mFlushLock);

    if (mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_1) {
    return mInterface->flush();
}

    return -ENOTSUP;
}

void Camera3Device::RequestThread::setPaused(bool paused) {
    Mutex::Autolock l(mPauseLock);
    mDoPause = paused;
+0 −7
Original line number Diff line number Diff line
@@ -166,8 +166,6 @@ class Camera3Device :

    status_t prepare(int maxCount, int streamId) override;

    uint32_t getDeviceVersion() override;

    ssize_t getJpegBufferSize(uint32_t width, uint32_t height) const override;
    ssize_t getPointCloudBufferSize() const;
    ssize_t getRawOpaqueBufferSize(int32_t width, int32_t height) const;
@@ -598,11 +596,6 @@ class Camera3Device :
     */
    static nsecs_t getMonoToBoottimeOffset();

    /**
     * Helper function to map between legacy and new dataspace enums
     */
    static android_dataspace mapToLegacyDataspace(android_dataspace dataSpace);

    /**
     * Helper functions to map between framework and HIDL values
     */
+0 −83
Original line number Diff line number Diff line
@@ -663,89 +663,6 @@ status_t Camera3Stream::disconnect() {
    }
}

status_t Camera3Stream::registerBuffersLocked(camera3_device *hal3Device) {
    ATRACE_CALL();

    /**
     * >= CAMERA_DEVICE_API_VERSION_3_2:
     *
     * camera3_device_t->ops->register_stream_buffers() is not called and must
     * be NULL.
     */
    if (hal3Device->common.version >= CAMERA_DEVICE_API_VERSION_3_2) {
        ALOGV("%s: register_stream_buffers unused as of HAL3.2", __FUNCTION__);

        if (hal3Device->ops->register_stream_buffers != NULL) {
            ALOGE("%s: register_stream_buffers is deprecated in HAL3.2; "
                    "must be set to NULL in camera3_device::ops", __FUNCTION__);
            return INVALID_OPERATION;
        }

        return OK;
    }

    ALOGV("%s: register_stream_buffers using deprecated code path", __FUNCTION__);

    status_t res;

    size_t bufferCount = getBufferCountLocked();

    Vector<buffer_handle_t*> buffers;
    buffers.insertAt(/*prototype_item*/NULL, /*index*/0, bufferCount);

    camera3_stream_buffer_set bufferSet = camera3_stream_buffer_set();
    bufferSet.stream = this;
    bufferSet.num_buffers = bufferCount;
    bufferSet.buffers = buffers.editArray();

    Vector<camera3_stream_buffer_t> streamBuffers;
    streamBuffers.insertAt(camera3_stream_buffer_t(), /*index*/0, bufferCount);

    // Register all buffers with the HAL. This means getting all the buffers
    // from the stream, providing them to the HAL with the
    // register_stream_buffers() method, and then returning them back to the
    // stream in the error state, since they won't have valid data.
    //
    // Only registered buffers can be sent to the HAL.

    uint32_t bufferIdx = 0;
    for (; bufferIdx < bufferCount; bufferIdx++) {
        res = getBufferLocked( &streamBuffers.editItemAt(bufferIdx) );
        if (res != OK) {
            ALOGE("%s: Unable to get buffer %d for registration with HAL",
                    __FUNCTION__, bufferIdx);
            // Skip registering, go straight to cleanup
            break;
        }

        sp<Fence> fence = new Fence(streamBuffers[bufferIdx].acquire_fence);
        fence->waitForever("Camera3Stream::registerBuffers");

        buffers.editItemAt(bufferIdx) = streamBuffers[bufferIdx].buffer;
    }
    if (bufferIdx == bufferCount) {
        // Got all buffers, register with HAL
        ALOGV("%s: Registering %zu buffers with camera HAL",
                __FUNCTION__, bufferCount);
        ATRACE_BEGIN("camera3->register_stream_buffers");
        res = hal3Device->ops->register_stream_buffers(hal3Device,
                &bufferSet);
        ATRACE_END();
    }

    // Return all valid buffers to stream, in ERROR state to indicate
    // they weren't filled.
    for (size_t i = 0; i < bufferIdx; i++) {
        streamBuffers.editItemAt(i).release_fence = -1;
        streamBuffers.editItemAt(i).status = CAMERA3_BUFFER_STATUS_ERROR;
        returnBufferLocked(streamBuffers[i], 0);
    }

    mPrepared = true;

    return res;
}

status_t Camera3Stream::getBufferLocked(camera3_stream_buffer *,
        const std::vector<size_t>&) {
    ALOGE("%s: This type of stream does not support output", __FUNCTION__);
Loading