• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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