1 /*
2  * Copyright (c) 2021-2023 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 #ifndef LOG_TAG
16 #define LOG_TAG "DeviceStatusListener"
17 #endif
18 
19 #include "device_status_listener.h"
20 #include <securec.h>
21 #include "hdf_device_class.h"
22 #include "v4_0/audio_types.h"
23 #ifdef BLUETOOTH_ENABLE
24 
25 #include "audio_bluetooth_manager.h"
26 #include "bluetooth_def.h"
27 
28 #endif
29 
30 #include "audio_errors.h"
31 #include "audio_info.h"
32 #include "audio_policy_log.h"
33 
34 namespace OHOS {
35 namespace AudioStandard {
36 const std::string AUDIO_HDI_SERVICE_NAME = "audio_manager_service";
37 const std::string AUDIO_HDI_PNP_SERVICE_NAME = "audio_hdi_pnp_service";
38 const std::string AUDIO_BLUETOOTH_HDI_SERVICE_NAME = "audio_bluetooth_hdi_service";
39 const std::string DAUDIO_HDI_SERVICE_NAME = "daudio_primary_service";
40 const std::string DP_ADDRESS = "card=0;port=";
41 const uint8_t EVENT_NUM_TYPE = 2;
42 const uint8_t EVENT_PARAMS = 4;
43 const uint8_t D_EVENT_PARAMS = 5;
44 
GetInternalDeviceType(PnpDeviceType pnpDeviceType)45 static DeviceType GetInternalDeviceType(PnpDeviceType pnpDeviceType)
46 {
47     DeviceType internalDeviceType = DEVICE_TYPE_NONE;
48 
49     switch (pnpDeviceType) {
50         case PnpDeviceType::PNP_DEVICE_HEADSET:
51             internalDeviceType = DEVICE_TYPE_WIRED_HEADSET;
52             break;
53         case PnpDeviceType::PNP_DEVICE_HEADPHONE:
54             internalDeviceType = DEVICE_TYPE_WIRED_HEADPHONES;
55             break;
56         case PnpDeviceType::PNP_DEVICE_USB_HEADSET:
57             internalDeviceType = DEVICE_TYPE_USB_HEADSET;
58             break;
59         case PnpDeviceType::PNP_DEVICE_ADAPTER_DEVICE:
60             internalDeviceType = DEVICE_TYPE_EXTERN_CABLE;
61             break;
62         case PnpDeviceType::PNP_DEVICE_DP_DEVICE:
63             internalDeviceType = DEVICE_TYPE_DP;
64             break;
65         case PnpDeviceType::PNP_DEVICE_MIC:
66             internalDeviceType = DEVICE_TYPE_MIC;
67             break;
68         default:
69             internalDeviceType = DEVICE_TYPE_NONE;
70             break;
71     }
72 
73     return internalDeviceType;
74 }
75 
ReceviceDistributedInfo(struct ServiceStatus * serviceStatus,std::string & info,DeviceStatusListener * devListener)76 static void ReceviceDistributedInfo(struct ServiceStatus* serviceStatus, std::string & info,
77     DeviceStatusListener * devListener)
78 {
79     if (serviceStatus->status == SERVIE_STATUS_START) {
80         AUDIO_DEBUG_LOG("distributed service online");
81     } else if (serviceStatus->status == SERVIE_STATUS_CHANGE && !info.empty()) {
82         DStatusInfo statusInfo;
83         statusInfo.connectType = ConnectType::CONNECT_TYPE_DISTRIBUTED;
84         PnpEventType pnpEventType = PNP_EVENT_UNKNOWN;
85         if (sscanf_s(info.c_str(), "EVENT_TYPE=%d;NID=%[^;];PIN=%d;VID=%d;IID=%d", &pnpEventType,
86             statusInfo.networkId, sizeof(statusInfo.networkId), &(statusInfo.hdiPin), &(statusInfo.mappingVolumeId),
87             &(statusInfo.mappingInterruptId)) < D_EVENT_PARAMS) {
88             AUDIO_ERR_LOG("[DeviceStatusListener]: Failed to scan info string");
89             return;
90         }
91 
92         statusInfo.isConnected = (pnpEventType == PNP_EVENT_DEVICE_ADD) ? true : false;
93         devListener->deviceObserver_.OnDeviceStatusUpdated(statusInfo);
94     } else if (serviceStatus->status == SERVIE_STATUS_STOP) {
95         AUDIO_DEBUG_LOG("distributed service offline");
96         DStatusInfo statusInfo;
97         devListener->deviceObserver_.OnDeviceStatusUpdated(statusInfo, true);
98     }
99 }
100 
OnDeviceStatusChange(const std::string & info,DeviceStatusListener * devListener)101 static void OnDeviceStatusChange(const std::string &info, DeviceStatusListener *devListener)
102 {
103     CHECK_AND_RETURN_LOG(!info.empty(), "OnDeviceStatusChange invalid info");
104     PnpDeviceType pnpDeviceType = PNP_DEVICE_UNKNOWN;
105     PnpEventType pnpEventType = PNP_EVENT_UNKNOWN;
106     if (sscanf_s(info.c_str(), "EVENT_TYPE=%d;DEVICE_TYPE=%d", &pnpEventType, &pnpDeviceType) < EVENT_PARAMS) {
107         AUDIO_WARNING_LOG("[DeviceStatusListener]: Failed to scan info string %{public}s", info.c_str());
108         return;
109     }
110 
111     DeviceType internalDevice = GetInternalDeviceType(pnpDeviceType);
112     AUDIO_DEBUG_LOG("internalDevice = %{public}d, pnpDeviceType = %{public}d", internalDevice, pnpDeviceType);
113     CHECK_AND_RETURN_LOG(internalDevice != DEVICE_TYPE_NONE, "Unsupported device %{public}d", pnpDeviceType);
114 
115     bool isConnected = (pnpEventType == PNP_EVENT_DEVICE_ADD) ? true : false;
116     AudioStreamInfo streamInfo = {};
117     devListener->deviceObserver_.OnDeviceStatusUpdated(internalDevice, isConnected, "", "", streamInfo);
118 }
119 
OnServiceStatusReceived(struct ServiceStatusListener * listener,struct ServiceStatus * serviceStatus)120 static void OnServiceStatusReceived(struct ServiceStatusListener *listener, struct ServiceStatus *serviceStatus)
121 {
122     CHECK_AND_RETURN_LOG(serviceStatus != nullptr, "Invalid ServiceStatus");
123     std::string info = serviceStatus->info;
124     AUDIO_INFO_LOG("OnServiceStatusReceived: [service name:%{public}s] [status:%{public}d]",
125         serviceStatus->serviceName, serviceStatus->status);
126 
127     DeviceStatusListener *devListener = reinterpret_cast<DeviceStatusListener *>(listener->priv);
128     CHECK_AND_RETURN_LOG(devListener != nullptr, "Invalid deviceStatusListener");
129     if (serviceStatus->serviceName == AUDIO_HDI_SERVICE_NAME) {
130         if (serviceStatus->status == SERVIE_STATUS_START) {
131             devListener->deviceObserver_.OnServiceConnected(AudioServiceIndex::HDI_SERVICE_INDEX);
132         } else if (serviceStatus->status == SERVIE_STATUS_STOP) {
133             devListener->deviceObserver_.OnServiceDisconnected(AudioServiceIndex::HDI_SERVICE_INDEX);
134         } else if (serviceStatus->status == SERVIE_STATUS_CHANGE) {
135             OnDeviceStatusChange(info, devListener);
136         }
137     } else if (serviceStatus->serviceName == AUDIO_BLUETOOTH_HDI_SERVICE_NAME) {
138 #ifdef BLUETOOTH_ENABLE
139         if (serviceStatus->status == SERVIE_STATUS_START) {
140             AUDIO_INFO_LOG("Bluetooth hdi service started");
141         } else if (serviceStatus->status == SERVIE_STATUS_STOP) {
142             AUDIO_INFO_LOG("Bluetooth hdi service stopped");
143             if (Bluetooth::AudioA2dpManager::HasA2dpDeviceConnected()) {
144                 AUDIO_ERR_LOG("Auto exit audio policy service for bluetooth hdi service crashed!");
145                 _Exit(0);
146             }
147         }
148 #endif
149     } else if (serviceStatus->serviceName == DAUDIO_HDI_SERVICE_NAME) {
150         ReceviceDistributedInfo(serviceStatus, info, devListener);
151     } else {
152         AUDIO_DEBUG_LOG("unkown service name.");
153     }
154 }
155 
DeviceStatusListener(IDeviceStatusObserver & observer)156 DeviceStatusListener::DeviceStatusListener(IDeviceStatusObserver &observer)
157     : deviceObserver_(observer), hdiServiceManager_(nullptr), listener_(nullptr) {}
158 
159 DeviceStatusListener::~DeviceStatusListener() = default;
160 
RegisterDeviceStatusListener()161 int32_t DeviceStatusListener::RegisterDeviceStatusListener()
162 {
163     AUDIO_INFO_LOG("Enter");
164     hdiServiceManager_ = HDIServiceManagerGet();
165     CHECK_AND_RETURN_RET_LOG(hdiServiceManager_ != nullptr, ERR_OPERATION_FAILED,
166         "[DeviceStatusListener]: Get HDI service manager failed");
167 
168     listener_ = HdiServiceStatusListenerNewInstance();
169     if (listener_ == nullptr) {
170         return ERR_ILLEGAL_STATE;
171     }
172     listener_->callback = OnServiceStatusReceived;
173     listener_->priv = (void *)this;
174     int32_t status = hdiServiceManager_->RegisterServiceStatusListener(hdiServiceManager_, listener_,
175         DeviceClass::DEVICE_CLASS_AUDIO);
176     CHECK_AND_RETURN_RET_LOG(status == HDF_SUCCESS, ERR_OPERATION_FAILED,
177         "[DeviceStatusListener]: Register service status listener failed");
178     AUDIO_INFO_LOG("Register service status listener finished");
179 
180     audioPnpServer_ = &AudioPnpServer::GetAudioPnpServer();
181     pnpDeviceCB_ = std::make_shared<AudioPnpStatusCallback>();
182     pnpDeviceCB_->SetDeviceStatusListener(this);
183     int32_t cbstatus = audioPnpServer_->RegisterPnpStatusListener(pnpDeviceCB_);
184     CHECK_AND_RETURN_RET_LOG(cbstatus == SUCCESS, ERR_OPERATION_FAILED,
185         "[DeviceStatusListener]: Register Pnp Status Listener failed");
186     AUDIO_INFO_LOG("Done");
187     return SUCCESS;
188 }
189 
UnRegisterDeviceStatusListener()190 int32_t DeviceStatusListener::UnRegisterDeviceStatusListener()
191 {
192     if ((hdiServiceManager_ == nullptr) || (listener_ == nullptr)) {
193         return ERR_ILLEGAL_STATE;
194     }
195     int32_t status = hdiServiceManager_->UnregisterServiceStatusListener(hdiServiceManager_, listener_);
196     CHECK_AND_RETURN_RET_LOG(status == HDF_SUCCESS, ERR_OPERATION_FAILED,
197         "[DeviceStatusListener]: UnRegister service status listener failed");
198 
199     hdiServiceManager_ = nullptr;
200     listener_ = nullptr;
201 
202     int32_t cbstatus = audioPnpServer_->UnRegisterPnpStatusListener();
203     if (cbstatus != SUCCESS) {
204         AUDIO_ERR_LOG("[DeviceStatusListener]: UnRegister Pnp Status Listener failed");
205         return ERR_OPERATION_FAILED;
206     }
207     audioPnpServer_ = nullptr;
208     pnpDeviceCB_ = nullptr;
209     return SUCCESS;
210 }
211 
OnPnpDeviceStatusChanged(const std::string & info)212 void DeviceStatusListener::OnPnpDeviceStatusChanged(const std::string &info)
213 {
214     CHECK_AND_RETURN_LOG(!info.empty(), "OnPnpDeviceStatusChange invalid info");
215     PnpDeviceType pnpDeviceType = PNP_DEVICE_UNKNOWN;
216     PnpEventType pnpEventType = PNP_EVENT_UNKNOWN;
217 
218     std::string name = "";
219     std::string address = "";
220 
221     if (sscanf_s(info.c_str(), "EVENT_TYPE=%d;DEVICE_TYPE=%d;", &pnpEventType, &pnpDeviceType) < EVENT_NUM_TYPE) {
222         AUDIO_ERR_LOG("Failed to scan info string %{public}s", info.c_str());
223         return;
224     }
225 
226     auto nameBegin = info.find("EVENT_NAME=");
227     auto nameEnd = info.find_first_of(";", nameBegin);
228     name = info.substr(nameBegin + std::strlen("EVENT_NAME="),
229         nameEnd - nameBegin - std::strlen("EVENT_NAME="));
230 
231     auto addressBegin = info.find("DEVICE_ADDRESS=");
232     auto addressEnd = info.find_first_of(";", addressBegin);
233     string portId = info.substr(addressBegin + std::strlen("DEVICE_ADDRESS="),
234         addressEnd - addressBegin - std::strlen("DEVICE_ADDRESS="));
235 
236     DeviceType internalDevice = GetInternalDeviceType(pnpDeviceType);
237     CHECK_AND_RETURN_LOG(internalDevice != DEVICE_TYPE_NONE, "Unsupported device %{public}d", pnpDeviceType);
238     bool isConnected = (pnpEventType == PNP_EVENT_DEVICE_ADD) ? true : false;
239 
240     if (internalDevice == DEVICE_TYPE_DP) {
241         address = DP_ADDRESS + portId;
242     }
243     AUDIO_INFO_LOG("[device type :%{public}d], [connection state: %{public}d] "
244         "[name: %{public}s]", internalDevice, isConnected, name.c_str());
245     deviceObserver_.OnPnpDeviceStatusUpdated(internalDevice, isConnected, name, address);
246 }
247 
OnMicrophoneBlocked(const std::string & info)248 void DeviceStatusListener::OnMicrophoneBlocked(const std::string &info)
249 {
250     CHECK_AND_RETURN_LOG(!info.empty(), "OnMicrophoneBlocked invalid info");
251 
252     PnpDeviceType pnpDeviceType = PNP_DEVICE_UNKNOWN;
253     PnpEventType pnpEventType = PNP_EVENT_UNKNOWN;
254 
255     if (sscanf_s(info.c_str(), "EVENT_TYPE=%d;DEVICE_TYPE=%d;", &pnpEventType, &pnpDeviceType) < EVENT_NUM_TYPE) {
256         AUDIO_ERR_LOG("Failed to scan info string %{public}s", info.c_str());
257         return;
258     }
259 
260     DeviceType micBlockedDeviceType = GetInternalDeviceType(pnpDeviceType);
261     CHECK_AND_RETURN_LOG(micBlockedDeviceType != DEVICE_TYPE_NONE, "Unsupported device %{public}d", pnpDeviceType);
262 
263     DeviceBlockStatus status = DEVICE_UNBLOCKED;
264     if (pnpEventType == PNP_EVENT_MIC_BLOCKED) {
265         status = DEVICE_BLOCKED;
266     }
267     AUDIO_INFO_LOG("[device type :%{public}d], [status :%{public}d]", micBlockedDeviceType, status);
268     deviceObserver_.OnMicrophoneBlockedUpdate(micBlockedDeviceType, status);
269 }
270 
AudioPnpStatusCallback()271 AudioPnpStatusCallback::AudioPnpStatusCallback()
272 {
273     AUDIO_INFO_LOG("ctor");
274 }
275 
~AudioPnpStatusCallback()276 AudioPnpStatusCallback::~AudioPnpStatusCallback() {}
277 
SetDeviceStatusListener(DeviceStatusListener * listener)278 void AudioPnpStatusCallback::SetDeviceStatusListener(DeviceStatusListener *listener)
279 {
280     listener_ = listener;
281 }
282 
OnPnpDeviceStatusChanged(const std::string & info)283 void AudioPnpStatusCallback::OnPnpDeviceStatusChanged(const std::string &info)
284 {
285     listener_->OnPnpDeviceStatusChanged(info);
286 }
287 
OnMicrophoneBlocked(const std::string & info)288 void AudioPnpStatusCallback::OnMicrophoneBlocked(const std::string &info)
289 {
290     listener_->OnMicrophoneBlocked(info);
291 }
292 } // namespace AudioStandard
293 } // namespace OHOS
294