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

Commit 35f60d25 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Solve the issue that the injection camera cannot be injected when the...

Merge "Solve the issue that the injection camera cannot be injected when the stream configuration is completed and the camera device is active"
parents 02313ea7 3b26818b
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -3854,7 +3854,6 @@ void CameraService::InjectionStatusListener::removeListener() {

void CameraService::InjectionStatusListener::notifyInjectionError(
        String8 injectedCamId, status_t err) {
    Mutex::Autolock lock(mListenerLock);
    if (mCameraInjectionCallback == nullptr) {
        ALOGW("InjectionStatusListener: mCameraInjectionCallback == nullptr");
        return;
@@ -3901,16 +3900,15 @@ void CameraService::InjectionStatusListener::notifyInjectionError(

void CameraService::InjectionStatusListener::binderDied(
        const wp<IBinder>& /*who*/) {
    Mutex::Autolock lock(mListenerLock);
    ALOGV("InjectionStatusListener: ICameraInjectionCallback has died");
    auto parent = mParent.promote();
    if (parent != nullptr) {
        parent->clearInjectionParameters();
        auto clientDescriptor = parent->mActiveClientManager.get(parent->mInjectionInternalCamId);
        if (clientDescriptor != nullptr) {
            BasicClient* baseClientPtr = clientDescriptor->getValue().get();
            baseClientPtr->stopInjection();
        }
        parent->clearInjectionParameters();
    }
}

@@ -3928,7 +3926,6 @@ binder::Status CameraService::CameraInjectionSession::stopInjection() {
    }

    status_t res = NO_ERROR;
    parent->clearInjectionParameters();
    auto clientDescriptor = parent->mActiveClientManager.get(parent->mInjectionInternalCamId);
    if (clientDescriptor != nullptr) {
        BasicClient* baseClientPtr = clientDescriptor->getValue().get();
@@ -3940,6 +3937,7 @@ binder::Status CameraService::CameraInjectionSession::stopInjection() {
                "Camera session encountered error");
        }
    }
    parent->clearInjectionParameters();
    return binder::Status::ok();
}

+36 −8
Original line number Diff line number Diff line
@@ -2823,17 +2823,28 @@ status_t Camera3Device::configureStreamsLocked(int operatingMode,
        mRequestBufferSM.onStreamsConfigured();
    }

    // First call injectCamera() and then run configureStreamsLocked() case:
    // 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
    // must wait until the internal camera configure streams before running the injection job to
    // configure the injection streams.
    if (mInjectionMethods->isInjecting()) {
        ALOGV("%s: Injection camera %s: Start to configure streams.",
        ALOGD("%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;
        }
    } else {
        // First run configureStreamsLocked() and then call injectCamera() case:
        // If the stream configuration has been completed and camera deive is active, but the
        // injection camera has not been injected yet, we need to store the stream configuration of
        // the internal camera (because the stream configuration of the injection camera is based
        // on the internal camera). When injecting occurs later, this configuration can be used by
        // the injection camera.
        ALOGV("%s: The stream configuration is complete and the camera device is active, but the"
              " injection camera has not been injected yet.", __FUNCTION__);
        mInjectionMethods->storeInjectionConfig(config, bufferSizes);
    }

    return OK;
@@ -6544,6 +6555,13 @@ status_t Camera3Device::injectCamera(const String8& injectedCamId,
    ALOGI("%s Injection camera: injectedCamId = %s", __FUNCTION__, injectedCamId.string());
    ATRACE_CALL();
    Mutex::Autolock il(mInterfaceLock);
    // When the camera device is active, injectCamera() and stopInjection() will call
    // internalPauseAndWaitLocked() and internalResumeLocked(), and then they will call
    // mStatusChanged.waitRelative(mLock, timeout) of waitUntilStateThenRelock(). But
    // mStatusChanged.waitRelative(mLock, timeout)'s parameter: mutex "mLock" must be in the locked
    // state, so we need to add "Mutex::Autolock l(mLock)" to lock the "mLock" before calling
    // waitUntilStateThenRelock().
    Mutex::Autolock l(mLock);

    status_t res = NO_ERROR;
    if (mInjectionMethods->isInjecting()) {
@@ -6566,16 +6584,25 @@ status_t Camera3Device::injectCamera(const String8& injectedCamId,
        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__);
    if (mInjectionMethods->isStreamConfigCompleteButNotInjected()) {
        ALOGD("%s: The opened camera is directly cast to the remote device.", __FUNCTION__);

        camera3::camera_stream_configuration injectionConfig;
        std::vector<uint32_t> injectionBufferSizes;
        mInjectionMethods->getInjectionConfig(&injectionConfig, &injectionBufferSizes);
        if (mOperatingMode < 0 || injectionConfig.num_streams <= 0
                    || injectionBufferSizes.size() <= 0) {
            ALOGE("Failed to inject camera due to abandoned configuration! "
                    "mOperatingMode: %d injectionConfig.num_streams: %d "
                    "injectionBufferSizes.size(): %zu", mOperatingMode,
                    injectionConfig.num_streams, injectionBufferSizes.size());
            return DEAD_OBJECT;
        }

        res = mInjectionMethods->injectCamera(
                injectionConfig, injectionBufferSizes);
        if (res != OK) {
@@ -6590,6 +6617,7 @@ status_t Camera3Device::injectCamera(const String8& injectedCamId,
status_t Camera3Device::stopInjection() {
    ALOGI("%s: Injection camera: stopInjection", __FUNCTION__);
    Mutex::Autolock il(mInterfaceLock);
    Mutex::Autolock l(mLock);
    return mInjectionMethods->stopInjection();
}

+22 −2
Original line number Diff line number Diff line
@@ -1361,25 +1361,34 @@ class Camera3Device :
        // when device is IDLE and request thread is paused.
        status_t injectCamera(
                camera3::camera_stream_configuration& injectionConfig,
                std::vector<uint32_t>& injectionBufferSizes);
                const std::vector<uint32_t>& injectionBufferSizes);

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

        bool isInjecting();

        bool isStreamConfigCompleteButNotInjected();

        const String8& getInjectedCamId() const;

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

        // When the streaming configuration is completed and the camera device is active, but the
        // injection camera has not yet been injected, the streaming configuration of the internal
        // camera will be stored first.
        void storeInjectionConfig(
                const camera3::camera_stream_configuration& injectionConfig,
                const 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);
                const std::vector<uint32_t>& injectionBufferSizes);

        // Disconnect the injection camera and delete the hal interface.
        void injectionDisconnectImpl();
@@ -1397,6 +1406,17 @@ class Camera3Device :
        // Generated injection camera hal interface.
        sp<HalInterface> mInjectedCamHalInterface;

        // Backup of the original camera hal result FMQ.
        std::unique_ptr<ResultMetadataQueue> mBackupResultMetadataQueue;

        // FMQ writes the result for the injection camera. Must be guarded by
        // mProcessCaptureResultLock.
        std::unique_ptr<ResultMetadataQueue> mInjectionResultMetadataQueue;

        // The flag indicates that the stream configuration is complete, the camera device is
        // active, but the injection camera has not yet been injected.
        bool mIsStreamConfigCompleteButNotInjected = false;

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

+41 −13
Original line number Diff line number Diff line
@@ -86,7 +86,7 @@ status_t Camera3Device::Camera3DeviceInjectionMethods::injectionInitialize(
        return DEAD_OBJECT;
    }

    std::unique_ptr<ResultMetadataQueue>& resQueue = parent->mResultMetadataQueue;
    std::unique_ptr<ResultMetadataQueue>& resQueue = mInjectionResultMetadataQueue;
    auto resultQueueRet = session->getCaptureResultMetadataQueue(
        [&resQueue](const auto& descriptor) {
            resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
@@ -127,10 +127,8 @@ status_t Camera3Device::Camera3DeviceInjectionMethods::injectionInitialize(

status_t Camera3Device::Camera3DeviceInjectionMethods::injectCamera(
        camera3::camera_stream_configuration& injectionConfig,
        std::vector<uint32_t>& injectionBufferSizes) {
        const std::vector<uint32_t>& injectionBufferSizes) {
    status_t res = NO_ERROR;
    mInjectionConfig = injectionConfig;
    mInjectionBufferSizes = injectionBufferSizes;

    if (mInjectedCamHalInterface == nullptr) {
        ALOGE("%s: mInjectedCamHalInterface does not exist!", __FUNCTION__);
@@ -148,7 +146,6 @@ status_t Camera3Device::Camera3DeviceInjectionMethods::injectCamera(
    if (parent->mStatus == STATUS_ACTIVE) {
        ALOGV("%s: Let the device be IDLE and the request thread is paused",
                __FUNCTION__);
        parent->mPauseStateNotify = true;
        res = parent->internalPauseAndWaitLocked(maxExpectedDuration);
        if (res != OK) {
            ALOGE("%s: Can't pause captures to inject camera!", __FUNCTION__);
@@ -188,7 +185,7 @@ status_t Camera3Device::Camera3DeviceInjectionMethods::injectCamera(
        ALOGV("%s: Restarting activity to inject camera", __FUNCTION__);
        // Reuse current operating mode and session parameters for new stream
        // config.
        parent->internalUpdateStatusLocked(STATUS_ACTIVE);
        parent->internalResumeLocked();
    }

    return OK;
@@ -196,6 +193,11 @@ status_t Camera3Device::Camera3DeviceInjectionMethods::injectCamera(

status_t Camera3Device::Camera3DeviceInjectionMethods::stopInjection() {
    status_t res = NO_ERROR;
    mIsStreamConfigCompleteButNotInjected = false;
    if (mInjectionConfig.streams != nullptr) {
        delete [] mInjectionConfig.streams;
        mInjectionConfig.streams = nullptr;
    }

    sp<Camera3Device> parent = mParent.promote();
    if (parent == nullptr) {
@@ -208,7 +210,6 @@ status_t Camera3Device::Camera3DeviceInjectionMethods::stopInjection() {
    if (parent->mStatus == STATUS_ACTIVE) {
        ALOGV("%s: Let the device be IDLE and the request thread is paused",
                __FUNCTION__);
        parent->mPauseStateNotify = true;
        res = parent->internalPauseAndWaitLocked(maxExpectedDuration);
        if (res != OK) {
            ALOGE("%s: Can't pause captures to stop injection!", __FUNCTION__);
@@ -229,7 +230,7 @@ status_t Camera3Device::Camera3DeviceInjectionMethods::stopInjection() {
        ALOGV("%s: Restarting activity to stop injection", __FUNCTION__);
        // Reuse current operating mode and session parameters for new stream
        // config.
        parent->internalUpdateStatusLocked(STATUS_ACTIVE);
        parent->internalResumeLocked();
    }

    return OK;
@@ -243,6 +244,10 @@ bool Camera3Device::Camera3DeviceInjectionMethods::isInjecting() {
    }
}

bool Camera3Device::Camera3DeviceInjectionMethods::isStreamConfigCompleteButNotInjected() {
    return mIsStreamConfigCompleteButNotInjected;
}

const String8& Camera3Device::Camera3DeviceInjectionMethods::getInjectedCamId()
        const {
    return mInjectedCamId;
@@ -260,10 +265,26 @@ void Camera3Device::Camera3DeviceInjectionMethods::getInjectionConfig(
    *injectionBufferSizes = mInjectionBufferSizes;
}

void Camera3Device::Camera3DeviceInjectionMethods::storeInjectionConfig(
        const camera3::camera_stream_configuration& injectionConfig,
        const std::vector<uint32_t>& injectionBufferSizes) {
    mIsStreamConfigCompleteButNotInjected = true;
    if (mInjectionConfig.streams != nullptr) {
        delete [] mInjectionConfig.streams;
        mInjectionConfig.streams = nullptr;
    }
    mInjectionConfig = injectionConfig;
    mInjectionConfig.streams =
        (android::camera3::camera_stream_t **) new camera_stream_t*[injectionConfig.num_streams];
    for (size_t i = 0; i < injectionConfig.num_streams; i++) {
        mInjectionConfig.streams[i] = injectionConfig.streams[i];
    }
    mInjectionBufferSizes = injectionBufferSizes;
}

status_t Camera3Device::Camera3DeviceInjectionMethods::injectionConfigureStreams(
        camera3::camera_stream_configuration& injectionConfig,
        std::vector<uint32_t>& injectionBufferSizes) {
        const std::vector<uint32_t>& injectionBufferSizes) {
    ATRACE_CALL();
    status_t res = NO_ERROR;

@@ -326,7 +347,6 @@ status_t Camera3Device::Camera3DeviceInjectionMethods::injectionConfigureStreams
            mInjectedCamId.string());

    auto rc = parent->mPreparerThread->resume();

    if (rc != OK) {
        ALOGE("%s: Injection camera %s: Preparer thread failed to resume!",
                 __FUNCTION__, mInjectedCamId.string());
@@ -380,10 +400,18 @@ status_t Camera3Device::Camera3DeviceInjectionMethods::replaceHalInterface(
        return INVALID_OPERATION;
    }

    if (keepBackup && mBackupHalInterface == nullptr) {
    if (keepBackup) {
        if (mBackupHalInterface == nullptr) {
            mBackupHalInterface = parent->mInterface;
    } else if (!keepBackup) {
        }
        if (mBackupResultMetadataQueue == nullptr) {
            mBackupResultMetadataQueue = std::move(parent->mResultMetadataQueue);
            parent->mResultMetadataQueue = std::move(mInjectionResultMetadataQueue);
        }
    } else {
        mBackupHalInterface = nullptr;
        parent->mResultMetadataQueue = std::move(mBackupResultMetadataQueue);
        mBackupResultMetadataQueue = nullptr;
    }
    parent->mInterface = newHalInterface;