1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "daudio_hdf_operate.h"
17
18#include <hdf_io_service_if.h>
19#include <hdf_base.h>
20
21#include "daudio_errorcode.h"
22#include "daudio_log.h"
23
24#undef DH_LOG_TAG
25#define DH_LOG_TAG "DAudioHdfServStatListener"
26
27namespace OHOS {
28namespace DistributedHardware {
29IMPLEMENT_SINGLE_INSTANCE(DaudioHdfOperate);
30void DAudioHdfServStatListener::OnReceive(const ServiceStatus& status)
31{
32    DHLOGI("Service status on receive.");
33    if (status.serviceName == AUDIO_SERVICE_NAME || status.serviceName == AUDIOEXT_SERVICE_NAME) {
34        callback_(status);
35    }
36}
37
38int32_t DaudioHdfOperate::LoadDaudioHDFImpl()
39{
40    if (audioServStatus_.load() == OHOS::HDI::ServiceManager::V1_0::SERVIE_STATUS_START &&
41        audioextServStatus_.load() == OHOS::HDI::ServiceManager::V1_0::SERVIE_STATUS_START) {
42        DHLOGD("Service has already start.");
43        return DH_SUCCESS;
44    }
45    servMgr_ = IServiceManager::Get();
46    devmgr_ = IDeviceManager::Get();
47    CHECK_NULL_RETURN(servMgr_, ERR_DH_AUDIO_NULLPTR);
48    CHECK_NULL_RETURN(devmgr_, ERR_DH_AUDIO_NULLPTR);
49
50    ::OHOS::sptr<IServStatListener> listener(
51        new DAudioHdfServStatListener(DAudioHdfServStatListener::StatusCallback([&](const ServiceStatus& status) {
52            DHLOGI("Load audio service status callback, serviceName: %{public}s, status: %{public}d",
53                status.serviceName.c_str(), status.status);
54            std::unique_lock<std::mutex> lock(hdfOperateMutex_);
55            if (status.serviceName == AUDIO_SERVICE_NAME) {
56                audioServStatus_.store(status.status);
57                hdfOperateCon_.notify_one();
58            } else if (status.serviceName == AUDIOEXT_SERVICE_NAME) {
59                audioextServStatus_.store(status.status);
60                hdfOperateCon_.notify_one();
61            }
62    })));
63    if (servMgr_->RegisterServiceStatusListener(listener, DEVICE_CLASS_AUDIO) != HDF_SUCCESS) {
64        DHLOGE("Failed to register the service status listener.");
65        return ERR_DH_AUDIO_NULLPTR;
66    }
67
68    int32_t ret = devmgr_->LoadDevice(AUDIO_SERVICE_NAME);
69    if (ret != HDF_SUCCESS && ret != HDF_ERR_DEVICE_BUSY) {
70        return ERR_DH_AUDIO_FAILED;
71    }
72    if (WaitLoadService(AUDIO_SERVICE_NAME) != DH_SUCCESS) {
73        DHLOGE("Wait load audio service failed!");
74        return ERR_DH_AUDIO_FAILED;
75    }
76    ret = devmgr_->LoadDevice(AUDIOEXT_SERVICE_NAME);
77    if (ret != HDF_SUCCESS && ret != HDF_ERR_DEVICE_BUSY) {
78        return ERR_DH_AUDIO_FAILED;
79    }
80    if (WaitLoadService(AUDIOEXT_SERVICE_NAME) != DH_SUCCESS) {
81        DHLOGE("Wait load provider service failed!");
82        return ERR_DH_AUDIO_FAILED;
83    }
84
85    if (servMgr_->UnregisterServiceStatusListener(listener) != HDF_SUCCESS) {
86        DHLOGE("Failed to unregister the service status listener.");
87    }
88    return DH_SUCCESS;
89}
90
91int32_t DaudioHdfOperate::WaitLoadService(const std::string& servName)
92{
93    std::unique_lock<std::mutex> lock(hdfOperateMutex_);
94    if (servName == AUDIO_SERVICE_NAME) {
95        DHLOGD("WaitLoadService start service %s, status %hu", servName.c_str(), this->audioServStatus_.load());
96        hdfOperateCon_.wait_for(lock, std::chrono::milliseconds(WAIT_TIME), [this] {
97            return (this->audioServStatus_.load() == OHOS::HDI::ServiceManager::V1_0::SERVIE_STATUS_START);
98        });
99
100        if (this->audioServStatus_.load() != OHOS::HDI::ServiceManager::V1_0::SERVIE_STATUS_START) {
101            DHLOGE("Wait load service %{public}s failed, status %{public}hu", servName.c_str(),
102                this->audioServStatus_.load());
103            return ERR_DH_AUDIO_FAILED;
104        }
105    }
106
107    if (servName == AUDIOEXT_SERVICE_NAME) {
108        DHLOGD("WaitLoadService start service %s, status %hu", servName.c_str(), this->audioextServStatus_.load());
109        hdfOperateCon_.wait_for(lock, std::chrono::milliseconds(WAIT_TIME), [this] {
110            return (this->audioextServStatus_.load() == OHOS::HDI::ServiceManager::V1_0::SERVIE_STATUS_START);
111        });
112
113        if (this->audioextServStatus_.load() != OHOS::HDI::ServiceManager::V1_0::SERVIE_STATUS_START) {
114            DHLOGE("Wait load service %{public}s failed, status %{public}hu", servName.c_str(),
115                this->audioextServStatus_.load());
116            return ERR_DH_AUDIO_FAILED;
117        }
118    }
119    return DH_SUCCESS;
120}
121
122int32_t DaudioHdfOperate::UnLoadDaudioHDFImpl()
123{
124    DHLOGI("UnLoad daudio hdf impl begin!");
125    devmgr_ = IDeviceManager::Get();
126    CHECK_NULL_RETURN(devmgr_, ERR_DH_AUDIO_NULLPTR);
127
128    int32_t ret = devmgr_->UnloadDevice(AUDIO_SERVICE_NAME);
129    if (ret != HDF_SUCCESS) {
130        DHLOGE("Unload audio service failed, ret: %{public}d", ret);
131    }
132    ret = devmgr_->UnloadDevice(AUDIOEXT_SERVICE_NAME);
133    if (ret != HDF_SUCCESS) {
134        DHLOGE("Unload device failed, ret: %{public}d", ret);
135    }
136    audioServStatus_.store(INVALID_VALUE);
137    audioextServStatus_.store(INVALID_VALUE);
138    DHLOGD("UnLoad daudio hdf impl end!");
139    return DH_SUCCESS;
140}
141} // namespace DistributedHardware
142} // namespace OHOS