Merge "Solve the issue that the injection camera cannot be injected when the stream configuration is completed and the camera device is active"
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index efb0a04..7b138a6 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -3854,7 +3854,6 @@
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::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 @@
}
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 @@
"Camera session encountered error");
}
}
+ parent->clearInjectionParameters();
return binder::Status::ok();
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 0101c58..e4c299c 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2823,17 +2823,28 @@
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 @@
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 @@
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::stopInjection() {
ALOGI("%s: Injection camera: stopInjection", __FUNCTION__);
Mutex::Autolock il(mInterfaceLock);
+ Mutex::Autolock l(mLock);
return mInjectionMethods->stopInjection();
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 53a696f..e67777d 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -1361,25 +1361,34 @@
// 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 @@
// 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;
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;