* Copyright (c) 2025-2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "hcamera_switch_session.h"
#include "camera_log.h"
#include "camera_util.h"
#include "hcamera_session_manager.h"
#include "hcapture_session.h"
#include "camera_error_code.h"
#include "hcamera_service.h"
#include "ipc_skeleton.h"
namespace OHOS {
namespace CameraStandard {
HCameraSwitchSession::HCameraSwitchSession()
{
MEDIA_INFO_LOG("HCameraSwitchSession::HCameraSwitchSession enter");
}
HCameraSwitchSession::~HCameraSwitchSession()
{
MEDIA_INFO_LOG("HCameraSwitchSession::~HCameraSwitchSession enter");
}
int32_t HCameraSwitchSession::OnCameraActive(
const std::string &cameraId, bool isRegisterCameraSwitchCallback, const CaptureSessionInfo &sessionInfo)
{
MEDIA_INFO_LOG(
"HCameraSwitchSession::OnCameraActive cameraId is: %{public}s,isRegisterCameraSwitchCallback is:%{public}d",
cameraId.c_str(),
isRegisterCameraSwitchCallback);
std::lock_guard<std::mutex> lock(switchCallbackLock_);
for (auto& switchCallback : setSwitchCallbackList_) {
switchCallback->OnCameraActive(cameraId, isRegisterCameraSwitchCallback, sessionInfo);
}
return CAMERA_OK;
}
int32_t HCameraSwitchSession::OnCameraUnactive(const std::string &cameraId)
{
MEDIA_INFO_LOG("HCameraService::OnCameraUnactive cameraId is: %{public}s", cameraId.c_str());
std::lock_guard<std::mutex> lock(switchCallbackLock_);
for (auto& switchCallback : setSwitchCallbackList_) {
switchCallback->OnCameraUnactive(cameraId);
}
return CAMERA_OK;
}
int32_t HCameraSwitchSession::OnCameraSwitch(
const std::string &oriCameraId, const std::string &destCameraId, bool status)
{
MEDIA_INFO_LOG(
"HCameraService::OnCameraSwitch oriCameraId is: %{public}s,destCameraId is:%{public}s, is:%{public}d",
oriCameraId.c_str(),
destCameraId.c_str(),
status);
std::lock_guard<std::mutex> lock(switchCallbackLock_);
for (auto& switchCallback : setSwitchCallbackList_) {
switchCallback->OnCameraSwitch(oriCameraId, destCameraId, status);
}
return CAMERA_OK;
}
int32_t HCameraSwitchSession::SetCallback(const sptr<ICameraSwitchSessionCallback> &callback)
{
MEDIA_INFO_LOG("HCameraSwitchSession::SetCallback enter pid is:%{public}d", IPCSkeleton::GetCallingPid());
std::lock_guard<std::mutex> lock(switchCallbackLock_);
if (callback) {
setSwitchCallbackList_.push_back(callback);
}
return CAMERA_OK;
}
int32_t HCameraSwitchSession::SwitchCamera(const std::string &oriCameraId, const std::string &destCameraId)
{
MEDIA_INFO_LOG("HCameraSwitchSession::SwitchCamera enter, oriCameraId=%{public}s,destCameraId=%{public}s",
oriCameraId.c_str(), destCameraId.c_str());
std::lock_guard<std::mutex> lock(switchEnableLock_);
captureSession_ = GetAppCameraSwitchSession();
if (captureSession_ != nullptr) {
sptr<ICameraSwitchSessionCallback> icameraAppSwitchSessionCallback_ =
captureSession_->GetAppCameraSwitchCallback();
if (icameraAppSwitchSessionCallback_ != nullptr) {
MEDIA_INFO_LOG("HCameraSwitchSession::notify app switchCamera");
icameraAppSwitchSessionCallback_->OnCameraUnactive(destCameraId);
bool isSwitchSuccess = true;
OnCameraSwitch(oriCameraId, destCameraId, isSwitchSuccess);
return CAMERA_OK;
}
}
MEDIA_INFO_LOG("HCameraSwitchSession::system forced switch");
notRegisterCaptureSession_ = GetNotRegistCameraSwitchSession();
CHECK_RETURN_RET_ELOG(notRegisterCaptureSession_ == nullptr,
CAMERA_INVALID_ARG, "HCameraSwitchSession::notRegisterCaptureSession_ is nullptr.");
sptr<HCameraDevice> cameraDevice_ = notRegisterCaptureSession_->GetCameraSwirchDevice();
CHECK_RETURN_RET_ELOG(
cameraDevice_ == nullptr, CAMERA_INVALID_ARG, "HCameraSwitchSession::GetCameraSwirchDevice is failed.");
int32_t retCode = CameraErrorCode::SUCCESS;
int32_t sensorOrientation = cameraDevice_->GetSensorOrientation();
MEDIA_INFO_LOG("SwitchCamera::GetSensorOrientation sensorOrientation is, %{public}d", sensorOrientation);
retCode = notRegisterCaptureSession_->Stop();
MEDIA_INFO_LOG("SwitchCamera::Stop failed!, %{public}d", retCode);
retCode = notRegisterCaptureSession_->BeginConfig();
CHECK_PRINT_ELOG(retCode != CAMERA_OK, "SwitchCamera::BeginConfig failed!, %{public}d", retCode);
retCode = notRegisterCaptureSession_->RemoveInput(cameraDevice_);
retCode = cameraDevice_->Close();
MEDIA_INFO_LOG("SwitchCamera::Close failed!, %{public}d", retCode);
cameraDevice_->UpdateCameraSwitchCameraId(destCameraId);
retCode = cameraDevice_->Open();
CHECK_PRINT_ELOG(retCode != CAMERA_OK, "SwitchCamera::Open failed!, %{public}d", retCode);
retCode = notRegisterCaptureSession_->AddInput(cameraDevice_);
CHECK_PRINT_ELOG(retCode != CAMERA_OK, "SwitchCamera::AddInput failed!, %{public}d", retCode);
retCode = SwitchCameraUpdateSetting(cameraDevice_, sensorOrientation);
CHECK_PRINT_ELOG(
retCode != CAMERA_OK, "SwitchCamera::SwitchCameraUpdateSetting failed!, %{public}d", retCode);
MEDIA_INFO_LOG("HCameraSwitchSession::SwitchCamera enter, CommitConfig(),sessionId=%{public}d",
notRegisterCaptureSession_->GetSessionId());
retCode = notRegisterCaptureSession_->CommitConfig();
CHECK_PRINT_ELOG(retCode != CAMERA_OK, "SwitchCamera::CommitConfig failed!, %{public}d", retCode);
int32_t sessionID = notRegisterCaptureSession_->GetSessionId();
notRegisterCaptureSession_->SetNotRegisterCameraSwitchSessionId(sessionID);
retCode = notRegisterCaptureSession_->Start();
CHECK_PRINT_ELOG(retCode != CAMERA_OK, "SwitchCamera::Start failed!, %{public}d", retCode);
bool result = (retCode == CAMERA_OK) ? true : false;
OnCameraSwitch(oriCameraId, destCameraId, result);
return CAMERA_OK;
}
int32_t HCameraSwitchSession::SwitchCameraUpdateSetting(
sptr<HCameraDevice> cameraDevice_, int32_t sensorOrientation)
{
MEDIA_INFO_LOG("HCameraSwitchSession::SwitchCameraUpdateSetting enter");
int32_t DEFAULT_ITEMS = 10;
int32_t DEFAULT_DATA_LENGTH = 100;
std::shared_ptr<OHOS::Camera::CameraMetadata> cameraSwitchMetadata =
std::make_shared<OHOS::Camera::CameraMetadata>(DEFAULT_ITEMS, DEFAULT_DATA_LENGTH);
camera_metadata_item_t item;
bool status = false;
int32_t ret;
int32_t value = OHOS_CAMERA_SWITCH_ON;
MEDIA_INFO_LOG("HCameraSwitchSession::SwitchCameraUpdateSetting sensorOrientation,%{public}d", sensorOrientation);
ret = OHOS::Camera::FindCameraMetadataItem(cameraSwitchMetadata->get(), OHOS_CONTROL_REQUEST_CAMERA_SWITCH, &item);
if (ret == CAM_META_ITEM_NOT_FOUND) {
status = cameraSwitchMetadata->addEntry(OHOS_CONTROL_REQUEST_CAMERA_SWITCH, &value, 1);
} else if (ret == CAM_META_SUCCESS) {
status = cameraSwitchMetadata->updateEntry(OHOS_CONTROL_REQUEST_CAMERA_SWITCH, &value, 1);
}
ret = OHOS::Camera::FindCameraMetadataItem(cameraSwitchMetadata->get(), OHOS_CONTROL_CAMERA_SWITCH_INFOS, &item);
if (ret == CAM_META_ITEM_NOT_FOUND) {
status = cameraSwitchMetadata->addEntry(OHOS_CONTROL_CAMERA_SWITCH_INFOS, &sensorOrientation, 1);
} else if (ret == CAM_META_SUCCESS) {
status = cameraSwitchMetadata->updateEntry(OHOS_CONTROL_CAMERA_SWITCH_INFOS, &sensorOrientation, 1);
}
ret = cameraDevice_->UpdateSetting(cameraSwitchMetadata);
CHECK_PRINT_ELOG(!status || ret != CameraErrorCode::SUCCESS, "SwitchCamera::UpdateSetting failed.");
return CAMERA_OK;
}
int32_t HCameraSwitchSession::SwitchSetService(const sptr<ICameraDeviceService> &cameraDevice)
{
MEDIA_INFO_LOG("HCameraSwitchSession::SwitchSetService enter");
switchSetService_ = static_cast<HCameraDevice *>(cameraDevice.GetRefPtr());
return CAMERA_OK;
}
sptr<HCaptureSession> HCameraSwitchSession::GetAppCameraSwitchSession()
{
MEDIA_INFO_LOG("HCameraSwitchSession::GetAppCameraSwitchSession enter");
auto &sessionManager = HCameraSessionManager::GetInstance();
auto totalSession = sessionManager.GetTotalSession();
for (auto &session : totalSession) {
MEDIA_INFO_LOG(
"HCameraSwitchSession::GetAppCameraSwitchSession GetSessionId:%{public}d", session->GetSessionId());
bool isFindSession = session->GetSessionId() == session->GetAppCameraSwitchSessionId();
CHECK_RETURN_RET(isFindSession, session);
}
MEDIA_INFO_LOG("HCameraSwitchSession::GetAppCameraSwitchSession is null");
return nullptr;
}
int32_t HCameraSwitchSession::CallbackEnter([[maybe_unused]] uint32_t code)
{
MEDIA_INFO_LOG("HCameraSwitchSession::CallbackEnter enter");
MEDIA_DEBUG_LOG("start, code:%{public}u", code);
return CAMERA_OK;
}
int32_t HCameraSwitchSession::CallbackExit([[maybe_unused]] uint32_t code, [[maybe_unused]] int32_t result)
{
MEDIA_DEBUG_LOG("HCameraSwitchSession::CallbackExit leave, code:%{public}u, result:%{public}d", code, result);
return CAMERA_OK;
}
sptr<HCaptureSession> HCameraSwitchSession::GetNotRegistCameraSwitchSession()
{
MEDIA_INFO_LOG("HCameraSwitchSession::GetNotRegistCameraSwitchSession enter");
auto &sessionManager = HCameraSessionManager::GetInstance();
auto totalSession = sessionManager.GetTotalSession();
for (auto &session : totalSession) {
MEDIA_INFO_LOG(
"HCameraSwitchSession::GetNotRegistCameraSwitchSession GetSessionId:%{public}d", session->GetSessionId());
bool isFindSession = session->GetSessionId() == session->GetNotRegisterCameraSwitchSessionId();
CHECK_RETURN_RET(isFindSession, session);
}
MEDIA_INFO_LOG("HCameraSwitchSession::GetNotRegistCameraSwitchSession is null");
return nullptr;
}
}
}