150a07fd2Sopenharmony_ci/*
250a07fd2Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
350a07fd2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
450a07fd2Sopenharmony_ci * you may not use this file except in compliance with the License.
550a07fd2Sopenharmony_ci * You may obtain a copy of the License at
650a07fd2Sopenharmony_ci *
750a07fd2Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
850a07fd2Sopenharmony_ci *
950a07fd2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1050a07fd2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1150a07fd2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1250a07fd2Sopenharmony_ci * See the License for the specific language governing permissions and
1350a07fd2Sopenharmony_ci * limitations under the License.
1450a07fd2Sopenharmony_ci */
1550a07fd2Sopenharmony_ci
1650a07fd2Sopenharmony_ci#include "daudio_hdf_operate.h"
1750a07fd2Sopenharmony_ci
1850a07fd2Sopenharmony_ci#include <hdf_io_service_if.h>
1950a07fd2Sopenharmony_ci#include <hdf_base.h>
2050a07fd2Sopenharmony_ci
2150a07fd2Sopenharmony_ci#include "daudio_errorcode.h"
2250a07fd2Sopenharmony_ci#include "daudio_log.h"
2350a07fd2Sopenharmony_ci
2450a07fd2Sopenharmony_ci#undef DH_LOG_TAG
2550a07fd2Sopenharmony_ci#define DH_LOG_TAG "DAudioHdfServStatListener"
2650a07fd2Sopenharmony_ci
2750a07fd2Sopenharmony_cinamespace OHOS {
2850a07fd2Sopenharmony_cinamespace DistributedHardware {
2950a07fd2Sopenharmony_ciIMPLEMENT_SINGLE_INSTANCE(DaudioHdfOperate);
3050a07fd2Sopenharmony_civoid DAudioHdfServStatListener::OnReceive(const ServiceStatus& status)
3150a07fd2Sopenharmony_ci{
3250a07fd2Sopenharmony_ci    DHLOGI("Service status on receive.");
3350a07fd2Sopenharmony_ci    if (status.serviceName == AUDIO_SERVICE_NAME || status.serviceName == AUDIOEXT_SERVICE_NAME) {
3450a07fd2Sopenharmony_ci        callback_(status);
3550a07fd2Sopenharmony_ci    }
3650a07fd2Sopenharmony_ci}
3750a07fd2Sopenharmony_ci
3850a07fd2Sopenharmony_ciint32_t DaudioHdfOperate::LoadDaudioHDFImpl()
3950a07fd2Sopenharmony_ci{
4050a07fd2Sopenharmony_ci    if (audioServStatus_.load() == OHOS::HDI::ServiceManager::V1_0::SERVIE_STATUS_START &&
4150a07fd2Sopenharmony_ci        audioextServStatus_.load() == OHOS::HDI::ServiceManager::V1_0::SERVIE_STATUS_START) {
4250a07fd2Sopenharmony_ci        DHLOGD("Service has already start.");
4350a07fd2Sopenharmony_ci        return DH_SUCCESS;
4450a07fd2Sopenharmony_ci    }
4550a07fd2Sopenharmony_ci    servMgr_ = IServiceManager::Get();
4650a07fd2Sopenharmony_ci    devmgr_ = IDeviceManager::Get();
4750a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(servMgr_, ERR_DH_AUDIO_NULLPTR);
4850a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(devmgr_, ERR_DH_AUDIO_NULLPTR);
4950a07fd2Sopenharmony_ci
5050a07fd2Sopenharmony_ci    ::OHOS::sptr<IServStatListener> listener(
5150a07fd2Sopenharmony_ci        new DAudioHdfServStatListener(DAudioHdfServStatListener::StatusCallback([&](const ServiceStatus& status) {
5250a07fd2Sopenharmony_ci            DHLOGI("Load audio service status callback, serviceName: %{public}s, status: %{public}d",
5350a07fd2Sopenharmony_ci                status.serviceName.c_str(), status.status);
5450a07fd2Sopenharmony_ci            std::unique_lock<std::mutex> lock(hdfOperateMutex_);
5550a07fd2Sopenharmony_ci            if (status.serviceName == AUDIO_SERVICE_NAME) {
5650a07fd2Sopenharmony_ci                audioServStatus_.store(status.status);
5750a07fd2Sopenharmony_ci                hdfOperateCon_.notify_one();
5850a07fd2Sopenharmony_ci            } else if (status.serviceName == AUDIOEXT_SERVICE_NAME) {
5950a07fd2Sopenharmony_ci                audioextServStatus_.store(status.status);
6050a07fd2Sopenharmony_ci                hdfOperateCon_.notify_one();
6150a07fd2Sopenharmony_ci            }
6250a07fd2Sopenharmony_ci    })));
6350a07fd2Sopenharmony_ci    if (servMgr_->RegisterServiceStatusListener(listener, DEVICE_CLASS_AUDIO) != HDF_SUCCESS) {
6450a07fd2Sopenharmony_ci        DHLOGE("Failed to register the service status listener.");
6550a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_NULLPTR;
6650a07fd2Sopenharmony_ci    }
6750a07fd2Sopenharmony_ci
6850a07fd2Sopenharmony_ci    int32_t ret = devmgr_->LoadDevice(AUDIO_SERVICE_NAME);
6950a07fd2Sopenharmony_ci    if (ret != HDF_SUCCESS && ret != HDF_ERR_DEVICE_BUSY) {
7050a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_FAILED;
7150a07fd2Sopenharmony_ci    }
7250a07fd2Sopenharmony_ci    if (WaitLoadService(AUDIO_SERVICE_NAME) != DH_SUCCESS) {
7350a07fd2Sopenharmony_ci        DHLOGE("Wait load audio service failed!");
7450a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_FAILED;
7550a07fd2Sopenharmony_ci    }
7650a07fd2Sopenharmony_ci    ret = devmgr_->LoadDevice(AUDIOEXT_SERVICE_NAME);
7750a07fd2Sopenharmony_ci    if (ret != HDF_SUCCESS && ret != HDF_ERR_DEVICE_BUSY) {
7850a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_FAILED;
7950a07fd2Sopenharmony_ci    }
8050a07fd2Sopenharmony_ci    if (WaitLoadService(AUDIOEXT_SERVICE_NAME) != DH_SUCCESS) {
8150a07fd2Sopenharmony_ci        DHLOGE("Wait load provider service failed!");
8250a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_FAILED;
8350a07fd2Sopenharmony_ci    }
8450a07fd2Sopenharmony_ci
8550a07fd2Sopenharmony_ci    if (servMgr_->UnregisterServiceStatusListener(listener) != HDF_SUCCESS) {
8650a07fd2Sopenharmony_ci        DHLOGE("Failed to unregister the service status listener.");
8750a07fd2Sopenharmony_ci    }
8850a07fd2Sopenharmony_ci    return DH_SUCCESS;
8950a07fd2Sopenharmony_ci}
9050a07fd2Sopenharmony_ci
9150a07fd2Sopenharmony_ciint32_t DaudioHdfOperate::WaitLoadService(const std::string& servName)
9250a07fd2Sopenharmony_ci{
9350a07fd2Sopenharmony_ci    std::unique_lock<std::mutex> lock(hdfOperateMutex_);
9450a07fd2Sopenharmony_ci    if (servName == AUDIO_SERVICE_NAME) {
9550a07fd2Sopenharmony_ci        DHLOGD("WaitLoadService start service %s, status %hu", servName.c_str(), this->audioServStatus_.load());
9650a07fd2Sopenharmony_ci        hdfOperateCon_.wait_for(lock, std::chrono::milliseconds(WAIT_TIME), [this] {
9750a07fd2Sopenharmony_ci            return (this->audioServStatus_.load() == OHOS::HDI::ServiceManager::V1_0::SERVIE_STATUS_START);
9850a07fd2Sopenharmony_ci        });
9950a07fd2Sopenharmony_ci
10050a07fd2Sopenharmony_ci        if (this->audioServStatus_.load() != OHOS::HDI::ServiceManager::V1_0::SERVIE_STATUS_START) {
10150a07fd2Sopenharmony_ci            DHLOGE("Wait load service %{public}s failed, status %{public}hu", servName.c_str(),
10250a07fd2Sopenharmony_ci                this->audioServStatus_.load());
10350a07fd2Sopenharmony_ci            return ERR_DH_AUDIO_FAILED;
10450a07fd2Sopenharmony_ci        }
10550a07fd2Sopenharmony_ci    }
10650a07fd2Sopenharmony_ci
10750a07fd2Sopenharmony_ci    if (servName == AUDIOEXT_SERVICE_NAME) {
10850a07fd2Sopenharmony_ci        DHLOGD("WaitLoadService start service %s, status %hu", servName.c_str(), this->audioextServStatus_.load());
10950a07fd2Sopenharmony_ci        hdfOperateCon_.wait_for(lock, std::chrono::milliseconds(WAIT_TIME), [this] {
11050a07fd2Sopenharmony_ci            return (this->audioextServStatus_.load() == OHOS::HDI::ServiceManager::V1_0::SERVIE_STATUS_START);
11150a07fd2Sopenharmony_ci        });
11250a07fd2Sopenharmony_ci
11350a07fd2Sopenharmony_ci        if (this->audioextServStatus_.load() != OHOS::HDI::ServiceManager::V1_0::SERVIE_STATUS_START) {
11450a07fd2Sopenharmony_ci            DHLOGE("Wait load service %{public}s failed, status %{public}hu", servName.c_str(),
11550a07fd2Sopenharmony_ci                this->audioextServStatus_.load());
11650a07fd2Sopenharmony_ci            return ERR_DH_AUDIO_FAILED;
11750a07fd2Sopenharmony_ci        }
11850a07fd2Sopenharmony_ci    }
11950a07fd2Sopenharmony_ci    return DH_SUCCESS;
12050a07fd2Sopenharmony_ci}
12150a07fd2Sopenharmony_ci
12250a07fd2Sopenharmony_ciint32_t DaudioHdfOperate::UnLoadDaudioHDFImpl()
12350a07fd2Sopenharmony_ci{
12450a07fd2Sopenharmony_ci    DHLOGI("UnLoad daudio hdf impl begin!");
12550a07fd2Sopenharmony_ci    devmgr_ = IDeviceManager::Get();
12650a07fd2Sopenharmony_ci    CHECK_NULL_RETURN(devmgr_, ERR_DH_AUDIO_NULLPTR);
12750a07fd2Sopenharmony_ci
12850a07fd2Sopenharmony_ci    int32_t ret = devmgr_->UnloadDevice(AUDIO_SERVICE_NAME);
12950a07fd2Sopenharmony_ci    if (ret != HDF_SUCCESS) {
13050a07fd2Sopenharmony_ci        DHLOGE("Unload audio service failed, ret: %{public}d", ret);
13150a07fd2Sopenharmony_ci    }
13250a07fd2Sopenharmony_ci    ret = devmgr_->UnloadDevice(AUDIOEXT_SERVICE_NAME);
13350a07fd2Sopenharmony_ci    if (ret != HDF_SUCCESS) {
13450a07fd2Sopenharmony_ci        DHLOGE("Unload device failed, ret: %{public}d", ret);
13550a07fd2Sopenharmony_ci    }
13650a07fd2Sopenharmony_ci    audioServStatus_.store(INVALID_VALUE);
13750a07fd2Sopenharmony_ci    audioextServStatus_.store(INVALID_VALUE);
13850a07fd2Sopenharmony_ci    DHLOGD("UnLoad daudio hdf impl end!");
13950a07fd2Sopenharmony_ci    return DH_SUCCESS;
14050a07fd2Sopenharmony_ci}
14150a07fd2Sopenharmony_ci} // namespace DistributedHardware
14250a07fd2Sopenharmony_ci} // namespace OHOS