1 /*
2 * Copyright (c) 2021-2025 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 <cstring>
22 #include "hdf_device_class.h"
23
24 namespace {
25 #include "v5_0/audio_types.h"
26 }
27
28
29 #ifdef BLUETOOTH_ENABLE
30
31 #include "audio_bluetooth_manager.h"
32 #include "bluetooth_def.h"
33
34 #endif
35
36 #include "audio_errors.h"
37 #include "audio_policy_log.h"
38 #include "audio_core_service.h"
39
40 namespace OHOS {
41 namespace AudioStandard {
42 const std::string AUDIO_HDI_SERVICE_NAME = "audio_manager_service";
43 const std::string AUDIO_HDI_PNP_SERVICE_NAME = "audio_hdi_pnp_service";
44 const std::string AUDIO_BLUETOOTH_HDI_SERVICE_NAME = "audio_bluetooth_hdi_service";
45 const std::string DAUDIO_HDI_SERVICE_NAME = "daudio_primary_service";
46 const std::string DP_ADDRESS = "card=0;port=";
47 const uint8_t EVENT_NUM_TYPE = 2;
48 const uint8_t EVENT_PARAMS = 4;
49 const uint8_t D_EVENT_PARAMS = 5;
50 const std::string DEVICE_STREAM_INFO_PREFIX = "CAPS=";
51
GetInternalDeviceType(PnpDeviceType pnpDeviceType)52 static DeviceType GetInternalDeviceType(PnpDeviceType pnpDeviceType)
53 {
54 DeviceType internalDeviceType = DEVICE_TYPE_NONE;
55
56 switch (pnpDeviceType) {
57 case PnpDeviceType::PNP_DEVICE_HEADSET:
58 internalDeviceType = DEVICE_TYPE_WIRED_HEADSET;
59 break;
60 case PnpDeviceType::PNP_DEVICE_HEADPHONE:
61 internalDeviceType = DEVICE_TYPE_WIRED_HEADPHONES;
62 break;
63 case PnpDeviceType::PNP_DEVICE_USB_HEADSET:
64 internalDeviceType = DEVICE_TYPE_USB_HEADSET;
65 break;
66 case PnpDeviceType::PNP_DEVICE_ADAPTER_DEVICE:
67 internalDeviceType = DEVICE_TYPE_EXTERN_CABLE;
68 break;
69 case PnpDeviceType::PNP_DEVICE_DP_DEVICE:
70 internalDeviceType = DEVICE_TYPE_DP;
71 break;
72 case PnpDeviceType::PNP_DEVICE_MIC:
73 internalDeviceType = DEVICE_TYPE_MIC;
74 break;
75 case PnpDeviceType::PNP_DEVICE_HDMI_DEVICE:
76 internalDeviceType = DEVICE_TYPE_HDMI;
77 break;
78 case PnpDeviceType::PNP_DEVICE_ACCESSORY:
79 internalDeviceType = DEVICE_TYPE_ACCESSORY;
80 break;
81 default:
82 internalDeviceType = DEVICE_TYPE_NONE;
83 break;
84 }
85
86 return internalDeviceType;
87 }
88
ParseDeviceStreamInfo(const std::string & info)89 static std::list<DeviceStreamInfo> ParseDeviceStreamInfo(const std::string &info)
90 {
91 std::string deviceStreamInfoStr;
92 auto pos = info.find(DEVICE_STREAM_INFO_PREFIX);
93 CHECK_AND_RETURN_RET_LOG(pos != std::string::npos, {}, "invalid info");
94 pos += DEVICE_STREAM_INFO_PREFIX.length();
95 auto endPos = info.find(";", pos);
96 deviceStreamInfoStr = endPos == std::string::npos ? info.substr(pos) : info.substr(pos, endPos - pos);
97 AUDIO_INFO_LOG("deviceStreamInfo: %{public}s", deviceStreamInfoStr.c_str());
98 return DeviceStreamInfo::DeserializeList(deviceStreamInfoStr);
99 }
100
ReceiveRemoteOffloadInfo(std::string & info,DStatusInfo & statusInfo)101 static void ReceiveRemoteOffloadInfo(std::string &info, DStatusInfo &statusInfo)
102 {
103 if (statusInfo.isConnected) {
104 CHECK_AND_RETURN(info.find(DEVICE_STREAM_INFO_PREFIX) != std::string::npos);
105 auto deviceStreamInfoList = ParseDeviceStreamInfo(info);
106 AUDIO_INFO_LOG("device stream info size: %{public}zu", deviceStreamInfoList.size());
107 statusInfo.streamInfo = deviceStreamInfoList;
108 std::list<std::string> supportDevices = { "Distributed_Output" };
109 AudioCoreService::GetCoreService()->UpdateStreamPropInfo("remote", "offload_distributed_output",
110 deviceStreamInfoList, supportDevices);
111 } else {
112 AudioCoreService::GetCoreService()->ClearStreamPropInfo("remote", "offload_distributed_output");
113 }
114 }
115
ReceviceDistributedInfo(struct ServiceStatus * serviceStatus,std::string & info,DeviceStatusListener * devListener)116 static void ReceviceDistributedInfo(struct ServiceStatus* serviceStatus, std::string & info,
117 DeviceStatusListener * devListener)
118 {
119 DStatusInfo statusInfo;
120 PnpEventType pnpEventType = PNP_EVENT_UNKNOWN;
121 if (serviceStatus->status == SERVIE_STATUS_START) {
122 AUDIO_DEBUG_LOG("distributed service online");
123 } else if (serviceStatus->status == SERVIE_STATUS_CHANGE && !info.empty()) {
124 statusInfo.connectType = ConnectType::CONNECT_TYPE_DISTRIBUTED;
125 if (sscanf_s(info.c_str(), "EVENT_TYPE=%d;NID=%[^;];PIN=%d;VID=%d;IID=%d", &pnpEventType,
126 statusInfo.networkId, sizeof(statusInfo.networkId), &(statusInfo.hdiPin), &(statusInfo.mappingVolumeId),
127 &(statusInfo.mappingInterruptId)) < D_EVENT_PARAMS) {
128 AUDIO_ERR_LOG("[DeviceStatusListener]: Failed to scan info string");
129 return;
130 }
131
132 statusInfo.isConnected = (pnpEventType == PNP_EVENT_DEVICE_ADD) ? true : false;
133 ReceiveRemoteOffloadInfo(info, statusInfo);
134 devListener->deviceObserver_.OnDeviceStatusUpdated(statusInfo);
135 } else if (serviceStatus->status == SERVIE_STATUS_STOP) {
136 AUDIO_DEBUG_LOG("distributed service offline");
137 JUDGE_AND_ERR_LOG(sscanf_s(info.c_str(), "EVENT_TYPE=%d;NID=%[^;];PIN=%d;VID=%d;IID=%d", &pnpEventType,
138 statusInfo.networkId, sizeof(statusInfo.networkId), &(statusInfo.hdiPin), &(statusInfo.mappingVolumeId),
139 &(statusInfo.mappingInterruptId)) < D_EVENT_PARAMS, "[DeviceStatusListener]: Failed to scan info string");
140 devListener->deviceObserver_.OnDeviceStatusUpdated(statusInfo, true);
141 }
142 }
143
OnDeviceStatusChange(const std::string & info,DeviceStatusListener * devListener)144 static void OnDeviceStatusChange(const std::string &info, DeviceStatusListener *devListener)
145 {
146 CHECK_AND_RETURN_LOG(!info.empty(), "OnDeviceStatusChange invalid info");
147 PnpDeviceType pnpDeviceType = PNP_DEVICE_UNKNOWN;
148 PnpEventType pnpEventType = PNP_EVENT_UNKNOWN;
149 if (sscanf_s(info.c_str(), "EVENT_TYPE=%d;DEVICE_TYPE=%d", &pnpEventType, &pnpDeviceType) < EVENT_PARAMS) {
150 AUDIO_WARNING_LOG("[DeviceStatusListener]: Failed to scan info string %{public}s", info.c_str());
151 return;
152 }
153
154 DeviceType internalDevice = GetInternalDeviceType(pnpDeviceType);
155 AUDIO_DEBUG_LOG("internalDevice = %{public}d, pnpDeviceType = %{public}d", internalDevice, pnpDeviceType);
156 if (internalDevice == DEVICE_TYPE_NONE) {
157 AUDIO_DEBUG_LOG("Unsupported device %{public}d", pnpDeviceType);
158 return;
159 }
160 bool isConnected = (pnpEventType == PNP_EVENT_DEVICE_ADD) ? true : false;
161 AudioStreamInfo streamInfo = {};
162 devListener->deviceObserver_.OnDeviceStatusUpdated(internalDevice, isConnected, "", "", streamInfo);
163 }
164
OnServiceStatusReceived(struct ServiceStatusListener * listener,struct ServiceStatus * serviceStatus)165 static void OnServiceStatusReceived(struct ServiceStatusListener *listener, struct ServiceStatus *serviceStatus)
166 {
167 CHECK_AND_RETURN_LOG(serviceStatus != nullptr, "Invalid ServiceStatus");
168 std::string info = serviceStatus->info;
169 AUDIO_INFO_LOG("OnServiceStatusReceived: [service name:%{public}s] [status:%{public}d]",
170 serviceStatus->serviceName, serviceStatus->status);
171
172 DeviceStatusListener *devListener = reinterpret_cast<DeviceStatusListener *>(listener->priv);
173 CHECK_AND_RETURN_LOG(devListener != nullptr, "Invalid deviceStatusListener");
174 if (serviceStatus->serviceName == AUDIO_HDI_SERVICE_NAME) {
175 if (serviceStatus->status == SERVIE_STATUS_START) {
176 devListener->deviceObserver_.OnServiceConnected(AudioServiceIndex::HDI_SERVICE_INDEX);
177 } else if (serviceStatus->status == SERVIE_STATUS_STOP) {
178 devListener->deviceObserver_.OnServiceDisconnected(AudioServiceIndex::HDI_SERVICE_INDEX);
179 } else if (serviceStatus->status == SERVIE_STATUS_CHANGE) {
180 OnDeviceStatusChange(info, devListener);
181 }
182 } else if (serviceStatus->serviceName == AUDIO_BLUETOOTH_HDI_SERVICE_NAME) {
183 #ifdef BLUETOOTH_ENABLE
184 if (serviceStatus->status == SERVIE_STATUS_START) {
185 AUDIO_INFO_LOG("Bluetooth hdi service started");
186 } else if (serviceStatus->status == SERVIE_STATUS_STOP) {
187 AUDIO_INFO_LOG("Bluetooth hdi service stopped");
188 if (Bluetooth::AudioA2dpManager::HasA2dpDeviceConnected()) {
189 AUDIO_ERR_LOG("Auto exit audio policy service for bluetooth hdi service crashed!");
190 _Exit(0);
191 }
192 }
193 #endif
194 } else if (serviceStatus->serviceName == DAUDIO_HDI_SERVICE_NAME) {
195 ReceviceDistributedInfo(serviceStatus, info, devListener);
196 } else {
197 AUDIO_DEBUG_LOG("unkown service name.");
198 }
199 }
200
DeviceStatusListener(IDeviceStatusObserver & observer)201 DeviceStatusListener::DeviceStatusListener(IDeviceStatusObserver &observer)
202 : deviceObserver_(observer), hdiServiceManager_(nullptr), listener_(nullptr) {}
203
204 DeviceStatusListener::~DeviceStatusListener() = default;
205
RegisterDeviceStatusListener()206 int32_t DeviceStatusListener::RegisterDeviceStatusListener()
207 {
208 AUDIO_INFO_LOG("Enter");
209 hdiServiceManager_ = HDIServiceManagerGet();
210 CHECK_AND_RETURN_RET_LOG(hdiServiceManager_ != nullptr, ERR_OPERATION_FAILED,
211 "[DeviceStatusListener]: Get HDI service manager failed");
212
213 listener_ = HdiServiceStatusListenerNewInstance();
214 CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, ERR_ILLEGAL_STATE,
215 "[DeviceStatusListener]: status listener failed");
216 listener_->callback = OnServiceStatusReceived;
217 listener_->priv = (void *)this;
218 int32_t status = hdiServiceManager_->RegisterServiceStatusListener(hdiServiceManager_, listener_,
219 DeviceClass::DEVICE_CLASS_AUDIO);
220 CHECK_AND_RETURN_RET_LOG(status == HDF_SUCCESS, ERR_OPERATION_FAILED,
221 "[DeviceStatusListener]: Register service status listener failed");
222 AUDIO_INFO_LOG("Register service status listener finished");
223
224 #ifdef AUDIO_WIRED_DETECT
225 audioPnpServer_ = &AudioPnpServer::GetAudioPnpServer();
226 pnpDeviceCB_ = std::make_shared<AudioPnpStatusCallback>();
227 pnpDeviceCB_->SetDeviceStatusListener(this);
228 int32_t cbstatus = audioPnpServer_->RegisterPnpStatusListener(pnpDeviceCB_);
229 CHECK_AND_RETURN_RET_LOG(cbstatus == SUCCESS, ERR_OPERATION_FAILED,
230 "[DeviceStatusListener]: Register Pnp Status Listener failed");
231 #endif
232 AUDIO_INFO_LOG("Done");
233 return SUCCESS;
234 }
235
UnRegisterDeviceStatusListener()236 int32_t DeviceStatusListener::UnRegisterDeviceStatusListener()
237 {
238 if ((hdiServiceManager_ == nullptr) || (listener_ == nullptr)) {
239 return ERR_ILLEGAL_STATE;
240 }
241 int32_t status = hdiServiceManager_->UnregisterServiceStatusListener(hdiServiceManager_, listener_);
242 CHECK_AND_RETURN_RET_LOG(status == HDF_SUCCESS, ERR_OPERATION_FAILED,
243 "[DeviceStatusListener]: UnRegister service status listener failed");
244
245 hdiServiceManager_ = nullptr;
246 listener_ = nullptr;
247
248 #ifdef AUDIO_WIRED_DETECT
249 int32_t cbstatus = audioPnpServer_->UnRegisterPnpStatusListener();
250 if (cbstatus != SUCCESS) {
251 AUDIO_ERR_LOG("[DeviceStatusListener]: UnRegister Pnp Status Listener failed");
252 return ERR_OPERATION_FAILED;
253 }
254 audioPnpServer_ = nullptr;
255 pnpDeviceCB_ = nullptr;
256 #endif
257 return SUCCESS;
258 }
259
260 #ifdef AUDIO_WIRED_DETECT
OnPnpDeviceStatusChanged(const std::string & info)261 void DeviceStatusListener::OnPnpDeviceStatusChanged(const std::string &info)
262 {
263 CHECK_AND_RETURN_LOG(!info.empty(), "OnPnpDeviceStatusChange invalid info");
264
265 if (audioDeviceAnahsCb_ != nullptr) {
266 std::string anahsName = "";
267 auto anahsBegin = info.find("ANAHS_NAME=");
268 auto anahsEnd = info.find_first_of(";", anahsBegin);
269 anahsName = info.substr(anahsBegin + std::strlen("ANAHS_NAME="),
270 anahsEnd - anahsBegin - std::strlen("ANAHS_NAME="));
271 if (strncmp(anahsName.c_str(), UEVENT_INSERT, strlen(UEVENT_INSERT)) == 0 ||
272 strncmp(anahsName.c_str(), UEVENT_REMOVE, strlen(UEVENT_REMOVE)) == 0) {
273 AUDIO_INFO_LOG("parse anahsName = %{public}s", anahsName.c_str());
274 audioDeviceAnahsCb_->OnExtPnpDeviceStatusChanged(anahsName, anahsShowType_);
275 return;
276 }
277 }
278
279 PnpDeviceType pnpDeviceType = PNP_DEVICE_UNKNOWN;
280 PnpEventType pnpEventType = PNP_EVENT_UNKNOWN;
281
282 AudioDeviceDescriptor desc = {};
283
284 if (sscanf_s(info.c_str(), "EVENT_TYPE=%d;DEVICE_TYPE=%d;", &pnpEventType, &pnpDeviceType) < EVENT_NUM_TYPE) {
285 AUDIO_ERR_LOG("Failed to scan info string %{public}s", info.c_str());
286 return;
287 }
288
289 auto nameBegin = info.find("EVENT_NAME=");
290 auto nameEnd = info.find_first_of(";", nameBegin);
291 desc.deviceName_ = info.substr(nameBegin + std::strlen("EVENT_NAME="),
292 nameEnd - nameBegin - std::strlen("EVENT_NAME="));
293
294 auto addressBegin = info.find("DEVICE_ADDRESS=");
295 auto addressEnd = info.find_first_of(";", addressBegin);
296 string portId = info.substr(addressBegin + std::strlen("DEVICE_ADDRESS="),
297 addressEnd - addressBegin - std::strlen("DEVICE_ADDRESS="));
298
299 desc.deviceType_ = GetInternalDeviceType(pnpDeviceType);
300 if (desc.deviceType_ == DEVICE_TYPE_NONE) {
301 AUDIO_DEBUG_LOG("Unsupported device %{public}d", pnpDeviceType);
302 return;
303 }
304 bool isConnected = (pnpEventType == PNP_EVENT_DEVICE_ADD) ? true : false;
305
306 if (desc.deviceType_ == DEVICE_TYPE_DP) {
307 desc.macAddress_ = DP_ADDRESS + portId;
308 }
309 AUDIO_INFO_LOG("[device type: %{public}d], [connection state: %{public}d], [name: %{public}s]",
310 desc.deviceType_, isConnected, desc.deviceName_.c_str());
311 deviceObserver_.OnPnpDeviceStatusUpdated(desc, isConnected);
312 }
313 #endif
314
SetAudioDeviceAnahsCallback(const sptr<IRemoteObject> & object)315 int32_t DeviceStatusListener::SetAudioDeviceAnahsCallback(const sptr<IRemoteObject> &object)
316 {
317 sptr<IStandardAudioAnahsManagerListener> listener = iface_cast<IStandardAudioAnahsManagerListener>(object);
318 if (listener != nullptr) {
319 audioDeviceAnahsCb_ = listener;
320 return SUCCESS;
321 } else {
322 return ERROR;
323 }
324 }
325
UnsetAudioDeviceAnahsCallback()326 int32_t DeviceStatusListener::UnsetAudioDeviceAnahsCallback()
327 {
328 audioDeviceAnahsCb_ = nullptr;
329 return SUCCESS;
330 }
331
UpdateAnahsPlatformType(std::string anahsShowType)332 void DeviceStatusListener::UpdateAnahsPlatformType(std::string anahsShowType)
333 {
334 anahsShowType_ = anahsShowType;
335 }
336
OnMicrophoneBlocked(const std::string & info)337 void DeviceStatusListener::OnMicrophoneBlocked(const std::string &info)
338 {
339 CHECK_AND_RETURN_LOG(!info.empty(), "OnMicrophoneBlocked invalid info");
340
341 PnpDeviceType pnpDeviceType = PNP_DEVICE_UNKNOWN;
342 PnpEventType pnpEventType = PNP_EVENT_UNKNOWN;
343
344 if (sscanf_s(info.c_str(), "EVENT_TYPE=%d;DEVICE_TYPE=%d;", &pnpEventType, &pnpDeviceType) < EVENT_NUM_TYPE) {
345 AUDIO_ERR_LOG("Failed to scan info string %{public}s", info.c_str());
346 return;
347 }
348
349 DeviceType micBlockedDeviceType = GetInternalDeviceType(pnpDeviceType);
350 if (micBlockedDeviceType == DEVICE_TYPE_NONE) {
351 AUDIO_DEBUG_LOG("Unsupported device %{public}d", pnpDeviceType);
352 return;
353 }
354
355 DeviceBlockStatus status = DEVICE_UNBLOCKED;
356 if (pnpEventType == PNP_EVENT_MIC_BLOCKED) {
357 status = DEVICE_BLOCKED;
358 }
359 AUDIO_INFO_LOG("[device type :%{public}d], [status :%{public}d]", micBlockedDeviceType, status);
360 deviceObserver_.OnMicrophoneBlockedUpdate(micBlockedDeviceType, status);
361 }
362
363 #ifdef AUDIO_WIRED_DETECT
AudioPnpStatusCallback()364 AudioPnpStatusCallback::AudioPnpStatusCallback()
365 {
366 AUDIO_INFO_LOG("ctor");
367 }
368
~AudioPnpStatusCallback()369 AudioPnpStatusCallback::~AudioPnpStatusCallback() {}
370
SetDeviceStatusListener(DeviceStatusListener * listener)371 void AudioPnpStatusCallback::SetDeviceStatusListener(DeviceStatusListener *listener)
372 {
373 listener_ = listener;
374 }
375
OnPnpDeviceStatusChanged(const std::string & info)376 void AudioPnpStatusCallback::OnPnpDeviceStatusChanged(const std::string &info)
377 {
378 listener_->OnPnpDeviceStatusChanged(info);
379 }
380
OnMicrophoneBlocked(const std::string & info)381 void AudioPnpStatusCallback::OnMicrophoneBlocked(const std::string &info)
382 {
383 listener_->OnMicrophoneBlocked(info);
384 }
385 #endif
386 } // namespace AudioStandard
387 } // namespace OHOS
388