Solve the issue that the injection camera cannot be injected when the stream configuration is completed and the camera device is active
It runs normally in “First call injectCamera() and then run
configureStreamsLocked()" case, but there are the following issues in
"First run configureStreamsLocked() and then call injectCamera()"
case:
- The streaming configuration of the internal camera is not stored
correctly.
Solution: Added storeInjectionConfig() to store internal configure
when the stream configuration is completed and injectCamera() has not
been called.
- After internalPauseAndWaitLocked(), readOneCameraMetadataLocked()
will have the problem of "Cannot read camera metadata from fmq",
resulting in removeInFlightRequestIfReadyLocked() unable to completely
clear mInFlightMap. The root cause is to directly override
mResultMetadataQueue in injectionInitialize(), but the above issue
will occur when the camera device is active.
Solution: Generate mInjectionResultMetadataQueue during
injectionInitialize(). When injecting camera, save the original
mResultMetadataQueue into mBackupResultMetadataQueue, and replace the
original mResultMetadataQueue with mInjectionResultMetadataQueue.
- 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
(https://source.corp.google.com/android/system/core/libutils/include/utils/Condition.h;l=67)
, so we need to add "Mutex::Autolock l(mLock)" here to lock the
"mLock" before calling internalPauseAndWaitLocked() or
internalResumeLocked(). If we don't do this, it may cause the mutex
"mLock" state to be out of order. After that, all functions that use
the mutex "mLock" will be in a waiting state, such as
clearStreamingRequest() called when the camera is closed.
Solution: Added "Mutex::Autolock l(mLock)" in injectCamera() and
stopInjection().
- Unable to run stopInjection() function from app.
Solution: First obtain the client descriptor from ActiveClientManager,
and then call clearInjectionParameters(), otherwise
mInjectionInternalCamId iscleared and the corresponding client
descriptor cannot be obtained.
Bug: 189289800
Test: Manual
Change-Id: If5ca8d7a8431d58d97214d5e6faa7a0e5013f862
diff --git a/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp b/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp
index f145dac..7026934 100644
--- a/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp
+++ b/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp
@@ -86,7 +86,7 @@
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::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 @@
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 @@
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::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 @@
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 @@
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::isStreamConfigCompleteButNotInjected() {
+ return mIsStreamConfigCompleteButNotInjected;
+}
+
const String8& Camera3Device::Camera3DeviceInjectionMethods::getInjectedCamId()
const {
return mInjectedCamId;
@@ -260,10 +265,26 @@
*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 @@
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 @@
return INVALID_OPERATION;
}
- if (keepBackup && mBackupHalInterface == nullptr) {
- mBackupHalInterface = parent->mInterface;
- } else if (!keepBackup) {
+ if (keepBackup) {
+ if (mBackupHalInterface == nullptr) {
+ mBackupHalInterface = parent->mInterface;
+ }
+ 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;