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 
27 namespace OHOS {
28 namespace DistributedHardware {
29 IMPLEMENT_SINGLE_INSTANCE(DaudioHdfOperate);
OnReceive(const ServiceStatus & status)30 void 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 
LoadDaudioHDFImpl()38 int32_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 
WaitLoadService(const std::string & servName)91 int32_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 
UnLoadDaudioHDFImpl()122 int32_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