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

Commit f985c0b7 authored by Cliff Wu's avatar Cliff Wu Committed by Automerger Merge Worker
Browse files

DynamicCamera: Injection camera switching mechanism in Camera3Device am: c2ad9c85

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/av/+/14243848

Change-Id: Id281a8041a863fb2998f03c6d9b5c50a45b9e9e1
parents 14b4ea99 c2ad9c85
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ cc_library_shared {
        "device3/RotateAndCropMapper.cpp",
        "device3/Camera3OutputStreamInterface.cpp",
        "device3/Camera3OutputUtils.cpp",
        "device3/Camera3DeviceInjectionMethods.cpp",
        "gui/RingBufferConsumer.cpp",
        "hidl/AidlCameraDeviceCallbacks.cpp",
        "hidl/AidlCameraServiceListener.cpp",
+226 −1
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@
#include <utils/Timers.h>
#include <cutils/properties.h>

#include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
#include <android/hardware/camera2/ICameraDeviceUser.h>

#include "utils/CameraTraces.h"
@@ -358,6 +359,8 @@ status_t Camera3Device::initializeCommonLocked() {
        }
    }

    mInjectionMethods = new Camera3DeviceInjectionMethods(this);

    return OK;
}

@@ -431,6 +434,10 @@ status_t Camera3Device::disconnectImpl() {
            mStatusTracker->join();
        }

        if (mInjectionMethods->isInjecting()) {
            mInjectionMethods->stopInjection();
        }

        HalInterface* interface;
        {
            Mutex::Autolock l(mLock);
@@ -1829,7 +1836,6 @@ status_t Camera3Device::waitUntilDrainedLocked(nsecs_t maxExpectedDuration) {
    return res;
}


void Camera3Device::internalUpdateStatusLocked(Status status) {
    mStatus = status;
    mRecentStatusUpdates.add(mStatus);
@@ -2820,6 +2826,19 @@ status_t Camera3Device::configureStreamsLocked(int operatingMode,
        mRequestBufferSM.onStreamsConfigured();
    }

    // Since the streams configuration of the injection camera is based on the internal camera, we
    // must wait until the internal camera configure streams before calling injectCamera() to
    // configure the injection streams.
    if (mInjectionMethods->isInjecting()) {
        ALOGV("%s: Injection camera %s: Start to configure streams.",
              __FUNCTION__, mInjectionMethods->getInjectedCamId().string());
        res = mInjectionMethods->injectCamera(config, bufferSizes);
        if (res != OK) {
            ALOGE("Can't finish inject camera process!");
            return res;
        }
    }

    return OK;
}

@@ -3524,6 +3543,146 @@ status_t Camera3Device::HalInterface::configureStreams(const camera_metadata_t *
    return res;
}

status_t Camera3Device::HalInterface::configureInjectedStreams(
        const camera_metadata_t* sessionParams, camera_stream_configuration* config,
        const std::vector<uint32_t>& bufferSizes,
        const CameraMetadata& cameraCharacteristics) {
    ATRACE_NAME("InjectionCameraHal::configureStreams");
    if (!valid()) return INVALID_OPERATION;
    status_t res = OK;

    if (config->input_is_multi_resolution) {
        ALOGE("%s: Injection camera device doesn't support multi-resolution input "
                "stream", __FUNCTION__);
        return BAD_VALUE;
    }

    // Convert stream config to HIDL
    std::set<int> activeStreams;
    device::V3_2::StreamConfiguration requestedConfiguration3_2;
    device::V3_4::StreamConfiguration requestedConfiguration3_4;
    device::V3_7::StreamConfiguration requestedConfiguration3_7;
    requestedConfiguration3_2.streams.resize(config->num_streams);
    requestedConfiguration3_4.streams.resize(config->num_streams);
    requestedConfiguration3_7.streams.resize(config->num_streams);
    for (size_t i = 0; i < config->num_streams; i++) {
        device::V3_2::Stream& dst3_2 = requestedConfiguration3_2.streams[i];
        device::V3_4::Stream& dst3_4 = requestedConfiguration3_4.streams[i];
        device::V3_7::Stream& dst3_7 = requestedConfiguration3_7.streams[i];
        camera3::camera_stream_t* src = config->streams[i];

        Camera3Stream* cam3stream = Camera3Stream::cast(src);
        cam3stream->setBufferFreedListener(this);
        int streamId = cam3stream->getId();
        StreamType streamType;
        switch (src->stream_type) {
            case CAMERA_STREAM_OUTPUT:
                streamType = StreamType::OUTPUT;
                break;
            case CAMERA_STREAM_INPUT:
                streamType = StreamType::INPUT;
                break;
            default:
                ALOGE("%s: Stream %d: Unsupported stream type %d", __FUNCTION__,
                        streamId, config->streams[i]->stream_type);
            return BAD_VALUE;
        }
        dst3_2.id = streamId;
        dst3_2.streamType = streamType;
        dst3_2.width = src->width;
        dst3_2.height = src->height;
        dst3_2.usage = mapToConsumerUsage(cam3stream->getUsage());
        dst3_2.rotation =
                mapToStreamRotation((camera_stream_rotation_t)src->rotation);
        // For HidlSession version 3.5 or newer, the format and dataSpace sent
        // to HAL are original, not the overridden ones.
        if (mHidlSession_3_5 != nullptr) {
            dst3_2.format = mapToPixelFormat(cam3stream->isFormatOverridden()
                                            ? cam3stream->getOriginalFormat()
                                            : src->format);
            dst3_2.dataSpace =
                    mapToHidlDataspace(cam3stream->isDataSpaceOverridden()
                                    ? cam3stream->getOriginalDataSpace()
                                    : src->data_space);
        } else {
            dst3_2.format = mapToPixelFormat(src->format);
            dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
        }
        dst3_4.v3_2 = dst3_2;
        dst3_4.bufferSize = bufferSizes[i];
        if (src->physical_camera_id != nullptr) {
            dst3_4.physicalCameraId = src->physical_camera_id;
        }
        dst3_7.v3_4 = dst3_4;
        dst3_7.groupId = cam3stream->getHalStreamGroupId();
        dst3_7.sensorPixelModesUsed.resize(src->sensor_pixel_modes_used.size());
        size_t j = 0;
        for (int mode : src->sensor_pixel_modes_used) {
            dst3_7.sensorPixelModesUsed[j++] =
                    static_cast<CameraMetadataEnumAndroidSensorPixelMode>(mode);
        }
        activeStreams.insert(streamId);
        // Create Buffer ID map if necessary
        mBufferRecords.tryCreateBufferCache(streamId);
    }
    // remove BufferIdMap for deleted streams
    mBufferRecords.removeInactiveBufferCaches(activeStreams);

    StreamConfigurationMode operationMode;
    res = mapToStreamConfigurationMode(
            (camera_stream_configuration_mode_t)config->operation_mode,
            /*out*/ &operationMode);
    if (res != OK) {
        return res;
    }
    requestedConfiguration3_7.operationMode = operationMode;
    size_t sessionParamSize = get_camera_metadata_size(sessionParams);
    requestedConfiguration3_7.operationMode = operationMode;
    requestedConfiguration3_7.sessionParams.setToExternal(
            reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(sessionParams)),
            sessionParamSize);

    // See which version of HAL we have
    if (mHidlSession_3_7 != nullptr) {
        requestedConfiguration3_7.streamConfigCounter = mNextStreamConfigCounter++;
        requestedConfiguration3_7.multiResolutionInputImage =
                config->input_is_multi_resolution;

        const camera_metadata_t* rawMetadata = cameraCharacteristics.getAndLock();
        ::android::hardware::camera::device::V3_2::CameraMetadata hidlChars = {};
        hidlChars.setToExternal(
                reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(rawMetadata)),
                get_camera_metadata_size(rawMetadata));
        cameraCharacteristics.unlock(rawMetadata);

        sp<hardware::camera::device::V3_7::ICameraInjectionSession>
                hidlInjectionSession_3_7;
        auto castInjectionResult_3_7 =
                device::V3_7::ICameraInjectionSession::castFrom(mHidlSession_3_7);
        if (castInjectionResult_3_7.isOk()) {
            hidlInjectionSession_3_7 = castInjectionResult_3_7;
        } else {
            ALOGE("%s: Transaction error: %s", __FUNCTION__,
                    castInjectionResult_3_7.description().c_str());
            return DEAD_OBJECT;
        }

        auto err = hidlInjectionSession_3_7->configureInjectionStreams(
                requestedConfiguration3_7, hidlChars);
        if (!err.isOk()) {
            ALOGE("%s: Transaction error: %s", __FUNCTION__,
                    err.description().c_str());
            return DEAD_OBJECT;
        }
    } else {
        ALOGE("%s: mHidlSession_3_7 does not exist, the lowest version of injection "
                "session is 3.7", __FUNCTION__);
        return DEAD_OBJECT;
    }

    return res;
}

status_t Camera3Device::HalInterface::wrapAsHidlRequest(camera_capture_request_t* request,
        /*out*/device::V3_2::CaptureRequest* captureRequest,
        /*out*/std::vector<native_handle_t*>* handlesCreated,
@@ -5724,6 +5883,18 @@ bool Camera3Device::RequestThread::overrideTestPattern(
    return changed;
}

status_t Camera3Device::RequestThread::setHalInterface(
        sp<HalInterface> newHalInterface) {
    if (newHalInterface.get() == nullptr) {
        ALOGE("%s: The newHalInterface does not exist!", __FUNCTION__);
        return DEAD_OBJECT;
    }

    mInterface = newHalInterface;

    return OK;
}

/**
 * PreparerThread inner class methods
 */
@@ -6367,4 +6538,58 @@ status_t Camera3Device::setCameraMute(bool enabled) {
    return mRequestThread->setCameraMute(enabled);
}

status_t Camera3Device::injectCamera(const String8& injectedCamId,
                                     sp<CameraProviderManager> manager) {
    ALOGI("%s Injection camera: injectedCamId = %s", __FUNCTION__, injectedCamId.string());
    ATRACE_CALL();
    Mutex::Autolock il(mInterfaceLock);

    status_t res = NO_ERROR;
    if (mInjectionMethods->isInjecting()) {
        if (injectedCamId == mInjectionMethods->getInjectedCamId()) {
            return OK;
        } else {
            res = mInjectionMethods->stopInjection();
            if (res != OK) {
                ALOGE("%s: Failed to stop the injection camera! ret != NO_ERROR: %d",
                        __FUNCTION__, res);
                return res;
            }
        }
    }

    res = mInjectionMethods->injectionInitialize(injectedCamId, manager, this);
    if (res != OK) {
        ALOGE("%s: Failed to initialize the injection camera! ret != NO_ERROR: %d",
                __FUNCTION__, res);
        return res;
    }

    camera3::camera_stream_configuration injectionConfig;
    std::vector<uint32_t> injectionBufferSizes;
    mInjectionMethods->getInjectionConfig(&injectionConfig, &injectionBufferSizes);
    // When the second display of android is cast to the remote device, and the opened camera is
    // also cast to the second display, in this case, because the camera has configured the streams
    // at this time, we can directly call injectCamera() to replace the internal camera with
    // injection camera.
    if (mOperatingMode >= 0 && injectionConfig.num_streams > 0
                && injectionBufferSizes.size() > 0) {
        ALOGV("%s: The opened camera is directly cast to the remote device.", __FUNCTION__);
        res = mInjectionMethods->injectCamera(
                injectionConfig, injectionBufferSizes);
        if (res != OK) {
            ALOGE("Can't finish inject camera process!");
            return res;
        }
    }

    return OK;
}

status_t Camera3Device::stopInjection() {
    ALOGI("%s: Injection camera: stopInjection", __FUNCTION__);
    Mutex::Autolock il(mInterfaceLock);
    return mInjectionMethods->stopInjection();
}

}; // namespace android
+91 −0
Original line number Diff line number Diff line
@@ -262,6 +262,18 @@ class Camera3Device :
    // Get the status trackeer for the camera device
    wp<camera3::StatusTracker> getStatusTracker() { return mStatusTracker; }

    /**
     * The injection camera session to replace the internal camera
     * session.
     */
    status_t injectCamera(const String8& injectedCamId,
                          sp<CameraProviderManager> manager);

    /**
     * Stop the injection camera and restore to internal camera session.
     */
    status_t stopInjection();

    /**
     * Helper functions to map between framework and HIDL values
     */
@@ -363,6 +375,13 @@ class Camera3Device :
                /*inout*/ camera_stream_configuration_t *config,
                const std::vector<uint32_t>& bufferSizes);

        // The injection camera configures the streams to hal.
        status_t configureInjectedStreams(
                const camera_metadata_t* sessionParams,
                /*inout*/ camera_stream_configuration_t* config,
                const std::vector<uint32_t>& bufferSizes,
                const CameraMetadata& cameraCharacteristics);

        // When the call succeeds, the ownership of acquire fences in requests is transferred to
        // HalInterface. More specifically, the current implementation will send the fence to
        // HAL process and close the FD in cameraserver process. When the call fails, the ownership
@@ -900,6 +919,9 @@ class Camera3Device :
                camera_metadata_enum_android_scaler_rotate_and_crop_t rotateAndCropValue);

        status_t setCameraMute(bool enabled);

        status_t setHalInterface(sp<HalInterface> newHalInterface);

      protected:

        virtual bool threadLoop();
@@ -1321,6 +1343,75 @@ class Camera3Device :
    // Whether the HAL supports camera muting via test pattern
    bool mSupportCameraMute = false;

    // Injection camera related methods.
    class Camera3DeviceInjectionMethods : public virtual RefBase {
      public:
        Camera3DeviceInjectionMethods(wp<Camera3Device> parent);

        ~Camera3DeviceInjectionMethods();

        // Initialize the injection camera and generate an hal interface.
        status_t injectionInitialize(
                const String8& injectedCamId, sp<CameraProviderManager> manager,
                const sp<
                    android::hardware::camera::device::V3_2 ::ICameraDeviceCallback>&
                    callback);

        // Injection camera will replace the internal camera and configure streams
        // when device is IDLE and request thread is paused.
        status_t injectCamera(
                camera3::camera_stream_configuration& injectionConfig,
                std::vector<uint32_t>& injectionBufferSizes);

        // Stop the injection camera and switch back to backup hal interface.
        status_t stopInjection();

        bool isInjecting();

        const String8& getInjectedCamId() const;

        void getInjectionConfig(/*out*/ camera3::camera_stream_configuration* injectionConfig,
                /*out*/ std::vector<uint32_t>* injectionBufferSizes);

      private:
        // Configure the streams of injection camera, it need wait until the
        // output streams are created and configured to the original camera before
        // proceeding.
        status_t injectionConfigureStreams(
                camera3::camera_stream_configuration& injectionConfig,
                std::vector<uint32_t>& injectionBufferSizes);

        // Disconnect the injection camera and delete the hal interface.
        void injectionDisconnectImpl();

        // Use injection camera hal interface to replace and backup original
        // camera hal interface.
        status_t replaceHalInterface(sp<HalInterface> newHalInterface,
                bool keepBackup);

        wp<Camera3Device> mParent;

        // Backup of the original camera hal interface.
        sp<HalInterface> mBackupHalInterface;

        // Generated injection camera hal interface.
        sp<HalInterface> mInjectedCamHalInterface;

        // Copy the configuration of the internal camera.
        camera3::camera_stream_configuration mInjectionConfig;

        // Copy the bufferSizes of the output streams of the internal camera.
        std::vector<uint32_t> mInjectionBufferSizes;

        // Synchronizes access to injection camera between initialize and
        // disconnect.
        Mutex mInjectionLock;

        // The injection camera ID.
        String8 mInjectedCamId;
    };
    sp<Camera3DeviceInjectionMethods> mInjectionMethods;

}; // class Camera3Device

}; // namespace android
+393 −0

File added.

Preview size limit exceeded, changes collapsed.