1 /*
2 * Copyright (c) 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 "AudioSocketThread"
17 #endif
18
19 #include "audio_socket_thread.h"
20 #include <cctype>
21 #include <cstdlib>
22 #include <dirent.h>
23 #include <linux/netlink.h>
24 #include <sys/socket.h>
25 #include <unistd.h>
26 #include <string>
27 #include "osal_time.h"
28 #include "audio_utils.h"
29 #include "audio_errors.h"
30 #include "securec.h"
31 #include "singleton.h"
32 #include "audio_policy_log.h"
33 #include "audio_pnp_server.h"
34 #include "audio_policy_server_handler.h"
35
36 namespace OHOS {
37 namespace AudioStandard {
38 using namespace std;
39 AudioEvent AudioSocketThread::audioSocketEvent_ = {
40 .eventType = AUDIO_EVENT_UNKNOWN,
41 .deviceType = AUDIO_DEVICE_UNKNOWN,
42 };
43
IsUpdatePnpDeviceState(AudioEvent * pnpDeviceEvent)44 bool AudioSocketThread::IsUpdatePnpDeviceState(AudioEvent *pnpDeviceEvent)
45 {
46 if (pnpDeviceEvent->eventType == audioSocketEvent_.eventType &&
47 pnpDeviceEvent->deviceType == audioSocketEvent_.deviceType &&
48 pnpDeviceEvent->name == audioSocketEvent_.name &&
49 pnpDeviceEvent->address == audioSocketEvent_.address &&
50 pnpDeviceEvent->anahsName == audioSocketEvent_.anahsName) {
51 return false;
52 }
53 return true;
54 }
55
UpdatePnpDeviceState(AudioEvent * pnpDeviceEvent)56 void AudioSocketThread::UpdatePnpDeviceState(AudioEvent *pnpDeviceEvent)
57 {
58 audioSocketEvent_.eventType = pnpDeviceEvent->eventType;
59 audioSocketEvent_.deviceType = pnpDeviceEvent->deviceType;
60 audioSocketEvent_.name = pnpDeviceEvent->name;
61 audioSocketEvent_.address = pnpDeviceEvent->address;
62 audioSocketEvent_.anahsName = pnpDeviceEvent->anahsName;
63 }
64
AudioPnpUeventOpen(int * fd)65 int AudioSocketThread::AudioPnpUeventOpen(int *fd)
66 {
67 int socketFd = -1;
68 int buffSize = UEVENT_SOCKET_BUFF_SIZE;
69 const int32_t on = 1; // turn on passcred
70 sockaddr_nl addr;
71
72 if (memset_s(&addr, sizeof(addr), 0, sizeof(addr)) != EOK) {
73 AUDIO_ERR_LOG("addr memset_s failed!");
74 return ERROR;
75 }
76 addr.nl_family = AF_NETLINK;
77 addr.nl_pid = ((uint32_t)gettid() << MOVE_NUM) | (uint32_t)getpid();
78 addr.nl_groups = UEVENT_SOCKET_GROUPS;
79
80 socketFd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
81 if (socketFd < 0) {
82 AUDIO_ERR_LOG("socket failed, %{public}d", errno);
83 return ERROR;
84 }
85
86 if (setsockopt(socketFd, SOL_SOCKET, SO_RCVBUF, &buffSize, sizeof(buffSize)) != 0) {
87 AUDIO_ERR_LOG("setsockopt SO_RCVBUF failed, %{public}d", errno);
88 CloseFd(socketFd);
89 return ERROR;
90 }
91
92 if (setsockopt(socketFd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) != 0) {
93 AUDIO_ERR_LOG("setsockopt SO_PASSCRED failed, %{public}d", errno);
94 CloseFd(socketFd);
95 return ERROR;
96 }
97
98 if (::bind(socketFd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
99 AUDIO_ERR_LOG("bind socket failed, %{public}d", errno);
100 CloseFd(socketFd);
101 return ERROR;
102 }
103
104 *fd = socketFd;
105 return SUCCESS;
106 }
107
AudioPnpReadUeventMsg(int sockFd,char * buffer,size_t length)108 ssize_t AudioSocketThread::AudioPnpReadUeventMsg(int sockFd, char *buffer, size_t length)
109 {
110 char credMsg[CMSG_SPACE(sizeof(struct ucred))] = {0};
111 iovec iov;
112 sockaddr_nl addr;
113 msghdr msghdr = {0};
114
115 memset_s(&addr, sizeof(addr), 0, sizeof(addr));
116
117 iov.iov_base = buffer;
118 iov.iov_len = length;
119
120 msghdr.msg_name = &addr;
121 msghdr.msg_namelen = sizeof(addr);
122 msghdr.msg_iov = &iov;
123 msghdr.msg_iovlen = 1;
124 msghdr.msg_control = credMsg;
125 msghdr.msg_controllen = sizeof(credMsg);
126
127 ssize_t len = recvmsg(sockFd, &msghdr, 0);
128 if (len <= 0) {
129 return ERROR;
130 }
131 cmsghdr *hdr = CMSG_FIRSTHDR(&msghdr);
132 if (hdr == NULL || hdr->cmsg_type != SCM_CREDENTIALS) {
133 AUDIO_ERR_LOG("Unexpected control message, ignored");
134 *buffer = '\0';
135 return ERROR;
136 }
137 return len;
138 }
139
SetAudioAnahsEventValue(AudioEvent * audioEvent,struct AudioPnpUevent * audioPnpUevent)140 int32_t AudioSocketThread::SetAudioAnahsEventValue(AudioEvent *audioEvent, struct AudioPnpUevent *audioPnpUevent)
141 {
142 if (strncmp(audioPnpUevent->subSystem, UEVENT_PLATFORM, strlen(UEVENT_PLATFORM)) == 0) {
143 if (strncmp(audioPnpUevent->anahsName, UEVENT_INSERT, strlen(UEVENT_INSERT)) == 0) {
144 AUDIO_INFO_LOG("set anahs event to insert.");
145 audioEvent->anahsName = UEVENT_INSERT;
146 return SUCCESS;
147 } else if (strncmp(audioPnpUevent->anahsName, UEVENT_REMOVE, strlen(UEVENT_REMOVE)) == 0) {
148 AUDIO_INFO_LOG("set anahs event to remove.");
149 audioEvent->anahsName = UEVENT_REMOVE;
150 return SUCCESS;
151 } else {
152 return ERROR;
153 }
154 }
155 return ERROR;
156 }
157
SetAudioPnpUevent(AudioEvent * audioEvent,struct AudioPnpUevent * audioPnpUevent,uint32_t h2wTypeLast)158 static void SetAudioPnpUevent(AudioEvent *audioEvent, struct AudioPnpUevent *audioPnpUevent, uint32_t h2wTypeLast)
159 {
160 switch (audioPnpUevent->switchState[0]) {
161 case REMOVE_AUDIO_DEVICE:
162 audioEvent->eventType = PNP_EVENT_DEVICE_REMOVE;
163 audioEvent->deviceType = h2wTypeLast;
164 break;
165 case ADD_DEVICE_HEADSET:
166 case ADD_DEVICE_HEADSET_WITHOUT_MIC:
167 audioEvent->eventType = PNP_EVENT_DEVICE_ADD;
168 audioEvent->deviceType = PNP_DEVICE_HEADSET;
169 break;
170 case ADD_DEVICE_ADAPTER:
171 audioEvent->eventType = PNP_EVENT_DEVICE_ADD;
172 audioEvent->deviceType = PNP_DEVICE_ADAPTER_DEVICE;
173 break;
174 default:
175 audioEvent->eventType = PNP_EVENT_DEVICE_ADD;
176 audioEvent->deviceType = PNP_DEVICE_UNKNOWN;
177 break;
178 }
179 }
180
SetAudioPnpServerEventValue(AudioEvent * audioEvent,struct AudioPnpUevent * audioPnpUevent)181 int32_t AudioSocketThread::SetAudioPnpServerEventValue(AudioEvent *audioEvent, struct AudioPnpUevent *audioPnpUevent)
182 {
183 if (strncmp(audioPnpUevent->subSystem, UEVENT_SUBSYSTEM_SWITCH, strlen(UEVENT_SUBSYSTEM_SWITCH)) == 0) {
184 static uint32_t h2wTypeLast = PNP_DEVICE_HEADSET;
185 if (strncmp(audioPnpUevent->switchName, UEVENT_SWITCH_NAME_H2W, strlen(UEVENT_SWITCH_NAME_H2W)) != 0) {
186 AUDIO_ERR_LOG("the switch name of 'h2w' not found!");
187 return ERROR;
188 }
189 SetAudioPnpUevent(audioEvent, audioPnpUevent, h2wTypeLast);
190 h2wTypeLast = audioEvent->deviceType;
191 audioEvent->name = audioPnpUevent->name;
192 audioEvent->address = audioPnpUevent->devName;
193 } else {
194 if (strncmp(audioPnpUevent->action, UEVENT_ACTION_CHANGE, strlen(UEVENT_ACTION_CHANGE)) != 0) {
195 return ERROR;
196 }
197 if (strstr(audioPnpUevent->name, UEVENT_NAME_HEADSET) == NULL) {
198 return ERROR;
199 }
200 if (strncmp(audioPnpUevent->devType, UEVENT_TYPE_EXTCON, strlen(UEVENT_TYPE_EXTCON)) != 0) {
201 return ERROR;
202 }
203 if (strstr(audioPnpUevent->state, UEVENT_STATE_ANALOG_HS0) != NULL) {
204 audioEvent->eventType = PNP_EVENT_DEVICE_REMOVE;
205 } else if (strstr(audioPnpUevent->state, UEVENT_STATE_ANALOG_HS1) != NULL) {
206 audioEvent->eventType = PNP_EVENT_DEVICE_ADD;
207 } else {
208 return ERROR;
209 }
210 audioEvent->deviceType = PNP_DEVICE_HEADSET;
211 }
212 return SUCCESS;
213 }
214
AudioAnahsDetectDevice(struct AudioPnpUevent * audioPnpUevent)215 int32_t AudioSocketThread::AudioAnahsDetectDevice(struct AudioPnpUevent *audioPnpUevent)
216 {
217 AudioEvent audioEvent;
218 if (audioPnpUevent == NULL) {
219 AUDIO_ERR_LOG("audioPnpUevent is null!");
220 return HDF_ERR_INVALID_PARAM;
221 }
222 if (SetAudioAnahsEventValue(&audioEvent, audioPnpUevent) != SUCCESS) {
223 return ERROR;
224 }
225
226 if (audioEvent.anahsName == audioSocketEvent_.anahsName) {
227 AUDIO_ERR_LOG("audio anahs device[%{public}u] state[%{public}u] not need flush !", audioEvent.deviceType,
228 audioEvent.eventType);
229 return SUCCESS;
230 }
231 audioSocketEvent_.anahsName = audioEvent.anahsName;
232 return SUCCESS;
233 }
234
AudioAnalogHeadsetDetectDevice(struct AudioPnpUevent * audioPnpUevent)235 int32_t AudioSocketThread::AudioAnalogHeadsetDetectDevice(struct AudioPnpUevent *audioPnpUevent)
236 {
237 AudioEvent audioEvent;
238 if (audioPnpUevent == NULL) {
239 AUDIO_ERR_LOG("audioPnpUevent is null!");
240 return HDF_ERR_INVALID_PARAM;
241 }
242
243 if (SetAudioPnpServerEventValue(&audioEvent, audioPnpUevent) != SUCCESS) {
244 return ERROR;
245 }
246 AUDIO_DEBUG_LOG("audio analog [%{public}s][%{public}s]",
247 audioEvent.deviceType == PNP_DEVICE_HEADSET ? "headset" : "headphone",
248 audioEvent.eventType == PNP_EVENT_DEVICE_ADD ? "add" : "removed");
249
250 if (!IsUpdatePnpDeviceState(&audioEvent)) {
251 AUDIO_ERR_LOG("audio analog device[%{public}u] state[%{public}u] not need flush !", audioEvent.deviceType,
252 audioEvent.eventType);
253 return SUCCESS;
254 }
255 UpdatePnpDeviceState(&audioEvent);
256 return SUCCESS;
257 }
258
AudioNnDetectDevice(struct AudioPnpUevent * audioPnpUevent)259 int32_t AudioSocketThread::AudioNnDetectDevice(struct AudioPnpUevent *audioPnpUevent)
260 {
261 if (audioPnpUevent == NULL) {
262 return HDF_ERR_INVALID_PARAM;
263 }
264
265 if ((strcmp(audioPnpUevent->action, "change") != 0) ||
266 (strncmp(audioPnpUevent->name, "send_nn_state", strlen("send_nn_state")) != 0)) {
267 return HDF_ERR_INVALID_PARAM;
268 }
269
270 std::string ueventStr = audioPnpUevent->name;
271 auto state = ueventStr.substr(ueventStr.find("send_nn_state") + strlen("send_nn_state") + 1);
272 int32_t nnState;
273 switch (atoi(state.c_str())) {
274 case STATE_NOT_SUPPORTED:
275 nnState = STATE_NOT_SUPPORTED;
276 break;
277 case STATE_NN_OFF:
278 nnState = STATE_NN_OFF;
279 break;
280 case STATE_NN_ON:
281 nnState = STATE_NN_ON;
282 break;
283 default:
284 AUDIO_ERR_LOG("NN state is invalid");
285 return HDF_ERR_INVALID_PARAM;
286 }
287
288 // callback of bluetooth
289 auto handle = DelayedSingleton<AudioPolicyServerHandler>::GetInstance();
290 if (handle == nullptr) {
291 AUDIO_ERR_LOG("get AudioPolicyServerHandler instance failed");
292 return HDF_ERR_INVALID_PARAM;
293 }
294 bool ret = handle->SendNnStateChangeCallback(nnState);
295 AUDIO_INFO_LOG("NN state change callback ret is [%{public}d]", ret);
296 return ret;
297 }
298
AudioDpDetectDevice(struct AudioPnpUevent * audioPnpUevent)299 int32_t AudioSocketThread::AudioDpDetectDevice(struct AudioPnpUevent *audioPnpUevent)
300 {
301 AudioEvent audioEvent = {0};
302 if (audioPnpUevent == NULL) {
303 return HDF_ERR_INVALID_PARAM;
304 }
305 if ((strcmp(audioPnpUevent->subSystem, "switch") != 0) ||
306 (strstr(audioPnpUevent->switchName, "hdmi_audio") == NULL) ||
307 (strcmp(audioPnpUevent->action, "change") != 0)) {
308 return HDF_ERR_INVALID_PARAM;
309 }
310
311 if (strcmp(audioPnpUevent->switchState, "1") == 0) {
312 audioEvent.eventType = PNP_EVENT_DEVICE_ADD;
313 } else if (strcmp(audioPnpUevent->switchState, "0") == 0) {
314 audioEvent.eventType = PNP_EVENT_DEVICE_REMOVE;
315 } else {
316 AUDIO_ERR_LOG("audio dp device [%{public}d]", audioEvent.eventType);
317 return ERROR;
318 }
319 audioEvent.deviceType = PNP_DEVICE_DP_DEVICE;
320
321 std::string switchNameStr = audioPnpUevent->switchName;
322
323 auto portBegin = switchNameStr.find("device_port=");
324 if (portBegin != switchNameStr.npos) {
325 audioEvent.name = switchNameStr.substr(portBegin + std::strlen("device_port="),
326 switchNameStr.length() - portBegin - std::strlen("device_port="));
327 }
328
329 auto addressBegin = switchNameStr.find("hdmi_audio");
330 auto addressEnd = switchNameStr.find_first_of("device_port", portBegin);
331 if (addressEnd != switchNameStr.npos) {
332 std::string portId = switchNameStr.substr(addressBegin + std::strlen("hdmi_audio"),
333 addressEnd - addressBegin - std::strlen("hdmi_audio")-1);
334 audioEvent.address = portId;
335 AUDIO_INFO_LOG("audio dp device portId:[%{public}s]", portId.c_str());
336 }
337
338 if (audioEvent.address.empty()) {
339 audioEvent.address = '0';
340 }
341 AUDIO_INFO_LOG("audio dp device [%{public}s]", audioEvent.eventType == PNP_EVENT_DEVICE_ADD ? "add" : "removed");
342
343 if (!IsUpdatePnpDeviceState(&audioEvent)) {
344 AUDIO_ERR_LOG("audio usb device[%{public}u] state[%{public}u] not need flush !", audioEvent.deviceType,
345 audioEvent.eventType);
346 return SUCCESS;
347 }
348 UpdatePnpDeviceState(&audioEvent);
349 return SUCCESS;
350 }
351
AudioMicBlockDevice(struct AudioPnpUevent * audioPnpUevent)352 int32_t AudioSocketThread::AudioMicBlockDevice(struct AudioPnpUevent *audioPnpUevent)
353 {
354 if (audioPnpUevent == nullptr) {
355 AUDIO_ERR_LOG("mic blocked audioPnpUevent is null");
356 return HDF_ERR_INVALID_PARAM;
357 }
358 AudioEvent audioEvent = {0};
359 if (strncmp(audioPnpUevent->name, "mic_blocked", strlen("mic_blocked")) == 0) {
360 audioEvent.eventType = PNP_EVENT_MIC_BLOCKED;
361 } else if (strncmp(audioPnpUevent->name, "mic_un_blocked", strlen("mic_un_blocked")) == 0) {
362 audioEvent.eventType = PNP_EVENT_MIC_UNBLOCKED;
363 } else {
364 return HDF_ERR_INVALID_PARAM;
365 }
366 audioEvent.deviceType = PNP_DEVICE_MIC;
367
368 AUDIO_INFO_LOG("mic blocked uevent info recv: %{public}s", audioPnpUevent->name);
369 UpdatePnpDeviceState(&audioEvent);
370 return SUCCESS;
371 }
372
AudioHDMIDetectDevice(struct AudioPnpUevent * audioPnpUevent)373 int32_t AudioSocketThread::AudioHDMIDetectDevice(struct AudioPnpUevent *audioPnpUevent)
374 {
375 AudioEvent audioEvent = {0};
376 if (audioPnpUevent == NULL) {
377 return HDF_ERR_INVALID_PARAM;
378 }
379 if ((strcmp(audioPnpUevent->subSystem, "switch") != 0) ||
380 (strstr(audioPnpUevent->switchName, "hdmi_mipi_audio") == NULL) ||
381 (strcmp(audioPnpUevent->action, "change") != 0)) {
382 AUDIO_DEBUG_LOG("AudioHDMIDetectDevice fail");
383 return HDF_ERR_INVALID_PARAM;
384 }
385
386 if (strcmp(audioPnpUevent->switchState, "1") == 0) {
387 audioEvent.eventType = PNP_EVENT_DEVICE_ADD;
388 } else if (strcmp(audioPnpUevent->switchState, "0") == 0) {
389 audioEvent.eventType = PNP_EVENT_DEVICE_REMOVE;
390 } else {
391 AUDIO_ERR_LOG("audio hdmi device [%{public}d]", audioEvent.eventType);
392 return ERROR;
393 }
394 audioEvent.deviceType = PNP_DEVICE_HDMI_DEVICE;
395
396 std::string switchNameStr = audioPnpUevent->switchName;
397
398 auto portBegin = switchNameStr.find("device_port=");
399 if (portBegin != switchNameStr.npos) {
400 audioEvent.name = switchNameStr.substr(portBegin + std::strlen("device_port="),
401 switchNameStr.length() - portBegin - std::strlen("device_port="));
402 }
403
404 auto addressBegin = switchNameStr.find("hdmi_mipi_audio");
405 auto addressEnd = switchNameStr.find_first_of("device_port", portBegin);
406 if (addressEnd != switchNameStr.npos) {
407 std::string portId = switchNameStr.substr(addressBegin + std::strlen("hdmi_mipi_audio"),
408 addressEnd - addressBegin - std::strlen("hdmi_mipi_audio")-1);
409 audioEvent.address = portId;
410 }
411
412 if (audioEvent.address.empty()) {
413 audioEvent.address = '0';
414 }
415 AUDIO_INFO_LOG("audio hdmi device [%{public}s]", audioEvent.eventType == PNP_EVENT_DEVICE_ADD ? "add" : "removed");
416
417 if (!IsUpdatePnpDeviceState(&audioEvent)) {
418 AUDIO_ERR_LOG("audio device[%{public}u] state[%{public}u] not need flush !", audioEvent.deviceType,
419 audioEvent.eventType);
420 return SUCCESS;
421 }
422 UpdatePnpDeviceState(&audioEvent);
423 return SUCCESS;
424 }
425
AudioPnpUeventParse(const char * msg,const ssize_t strLength)426 bool AudioSocketThread::AudioPnpUeventParse(const char *msg, const ssize_t strLength)
427 {
428 struct AudioPnpUevent audioPnpUevent = {"", "", "", "", "", "", "", "", "", ""};
429
430 if (strncmp(msg, "libudev", strlen("libudev")) == 0) {
431 return false;
432 }
433
434 if (strLength > UEVENT_MSG_LEN + 1) {
435 AUDIO_ERR_LOG("strLength > UEVENT_MSG_LEN + 1");
436 return false;
437 }
438 AUDIO_DEBUG_LOG("Param strLength: %{public}zu msg:[%{public}s] len:[%{public}zu]", strLength, msg, strlen(msg));
439 for (const char *msgTmp = msg; msgTmp < (msg + strLength);) {
440 if (*msgTmp == '\0') {
441 msgTmp++;
442 continue;
443 }
444 AUDIO_DEBUG_LOG("Param msgTmp:[%{private}s] len:[%{public}zu]", msgTmp, strlen(msgTmp));
445 const char *arrStrTmp[UEVENT_ARR_SIZE] = {
446 UEVENT_ACTION, UEVENT_DEV_NAME, UEVENT_NAME, UEVENT_STATE, UEVENT_DEVTYPE,
447 UEVENT_SUBSYSTEM, UEVENT_SWITCH_NAME, UEVENT_SWITCH_STATE, UEVENT_HDI_NAME,
448 UEVENT_ANAHS
449 };
450 const char **arrVarTmp[UEVENT_ARR_SIZE] = {
451 &audioPnpUevent.action, &audioPnpUevent.devName, &audioPnpUevent.name,
452 &audioPnpUevent.state, &audioPnpUevent.devType, &audioPnpUevent.subSystem,
453 &audioPnpUevent.switchName, &audioPnpUevent.switchState, &audioPnpUevent.hidName,
454 &audioPnpUevent.anahsName
455 };
456 for (int count = 0; count < UEVENT_ARR_SIZE; count++) {
457 if (strncmp(msgTmp, arrStrTmp[count], strlen(arrStrTmp[count])) == 0) {
458 msgTmp += strlen(arrStrTmp[count]);
459 *arrVarTmp[count] = msgTmp;
460 break;
461 }
462 }
463 msgTmp += strlen(msgTmp) + 1;
464 }
465
466 if ((AudioAnalogHeadsetDetectDevice(&audioPnpUevent) == SUCCESS) ||
467 (AudioHDMIDetectDevice(&audioPnpUevent) == SUCCESS) ||
468 (AudioDpDetectDevice(&audioPnpUevent) == SUCCESS) ||
469 (AudioAnahsDetectDevice(&audioPnpUevent) == SUCCESS) ||
470 (AudioNnDetectDevice(&audioPnpUevent) == SUCCESS) ||
471 (AudioMicBlockDevice(&audioPnpUevent) == SUCCESS)) {
472 return true;
473 }
474
475 return false;
476 }
477
DetectAnalogHeadsetState(AudioEvent * audioEvent)478 int32_t AudioSocketThread::DetectAnalogHeadsetState(AudioEvent *audioEvent)
479 {
480 int8_t state = 0;
481 FILE *fp = fopen(SWITCH_STATE_PATH, "r");
482 if (fp == NULL) {
483 AUDIO_ERR_LOG("audio open switch state node fail, %{public}d", errno);
484 return HDF_ERR_INVALID_PARAM;
485 }
486
487 size_t ret = fread(&state, STATE_PATH_ITEM_SIZE, STATE_PATH_ITEM_SIZE, fp);
488 if (ret == 0) {
489 fclose(fp);
490 AUDIO_ERR_LOG("audio read switch state node fail, %{public}d", errno);
491 return ERROR;
492 }
493
494 if (state == '0') {
495 audioEvent->eventType = AUDIO_DEVICE_REMOVE;
496 audioEvent->deviceType = AUDIO_HEADSET;
497 } else {
498 audioEvent->eventType = AUDIO_DEVICE_ADD;
499 audioEvent->deviceType = AUDIO_HEADSET;
500 }
501
502 fclose(fp);
503 return SUCCESS;
504 }
505
UpdateDeviceState(AudioEvent audioEvent)506 void AudioSocketThread::UpdateDeviceState(AudioEvent audioEvent)
507 {
508 char pnpInfo[AUDIO_EVENT_INFO_LEN_MAX] = {0};
509 int32_t ret;
510 if (!IsUpdatePnpDeviceState(&audioEvent)) {
511 AUDIO_ERR_LOG("audio first pnp device[%{public}u] state[%{public}u] not need flush !", audioEvent.deviceType,
512 audioEvent.eventType);
513 return;
514 }
515 ret = snprintf_s(pnpInfo, AUDIO_EVENT_INFO_LEN_MAX, AUDIO_EVENT_INFO_LEN_MAX - 1, "EVENT_TYPE=%u;DEVICE_TYPE=%u",
516 audioEvent.eventType, audioEvent.deviceType);
517 if (ret < 0) {
518 AUDIO_ERR_LOG("snprintf_s fail!");
519 return;
520 }
521
522 UpdatePnpDeviceState(&audioEvent);
523 return;
524 }
525
DetectDPState(AudioEvent * audioEvent)526 int32_t AudioSocketThread::DetectDPState(AudioEvent *audioEvent)
527 {
528 for (size_t i = 0; i <= DP_PORT_COUNT; ++i) {
529 std::string statePath = DP_PATH;
530 std::string namePath = DP_PATH;
531
532 if (i == 0) {
533 statePath.append("/state");
534 namePath.append("/name");
535 } else {
536 statePath.append(std::to_string(i) + "/state");
537 namePath.append(std::to_string(i) + "/name");
538 }
539
540 int32_t ret = ReadAndScanDpState(statePath, audioEvent->eventType);
541 if (ret != SUCCESS || audioEvent->eventType != PNP_EVENT_DEVICE_ADD) continue;
542
543 ret = ReadAndScanDpName(namePath, audioEvent->name);
544 if (ret != SUCCESS) continue;
545
546 audioEvent->deviceType = PNP_DEVICE_DP_DEVICE;
547 audioEvent->address = std::to_string(i);
548
549 AUDIO_INFO_LOG("dp device reconnect when server start");
550 return SUCCESS;
551 }
552 return ERROR;
553 }
554
ReadAndScanDpState(const std::string & path,uint32_t & eventType)555 int32_t AudioSocketThread::ReadAndScanDpState(const std::string &path, uint32_t &eventType)
556 {
557 int8_t state = 0;
558
559 FILE *fp = fopen(path.c_str(), "r");
560 if (fp == nullptr) {
561 AUDIO_ERR_LOG("audio open dp state node fail, %{public}d", errno);
562 return HDF_ERR_INVALID_PARAM;
563 }
564 size_t ret = fread(&state, STATE_PATH_ITEM_SIZE, STATE_PATH_ITEM_SIZE, fp);
565 if (ret == 0) {
566 fclose(fp);
567 AUDIO_ERR_LOG("audio read dp state node fail, %{public}d", errno);
568 return ERROR;
569 }
570 int32_t closeRet = fclose(fp);
571 if (closeRet != 0) {
572 AUDIO_ERR_LOG("something wrong when fclose! err:%{public}d", errno);
573 }
574
575 if (state == '1') {
576 eventType = PNP_EVENT_DEVICE_ADD;
577 } else if (state == '0') {
578 eventType = PNP_EVENT_DEVICE_REMOVE;
579 return ERROR;
580 } else {
581 AUDIO_ERR_LOG("audio dp device [%{public}d]", eventType);
582 return ERROR;
583 }
584 AUDIO_DEBUG_LOG("audio read dp state path: %{public}s, event type: %{public}d",
585 path.c_str(), eventType);
586 return SUCCESS;
587 }
588
ReadAndScanDpName(const std::string & path,std::string & name)589 int32_t AudioSocketThread::ReadAndScanDpName(const std::string &path, std::string &name)
590 {
591 char deviceName[AUDIO_PNP_INFO_LEN_MAX];
592
593 FILE *fp = fopen(path.c_str(), "r");
594 if (fp == nullptr) {
595 AUDIO_ERR_LOG("audio open dp name node fail, %{public}d", errno);
596 return HDF_ERR_INVALID_PARAM;
597 }
598 size_t ret = fread(&deviceName, STATE_PATH_ITEM_SIZE, AUDIO_PNP_INFO_LEN_MAX, fp);
599 if (ret == 0) {
600 fclose(fp);
601 AUDIO_ERR_LOG("audio read dp name node fail, %{public}d", errno);
602 return ERROR;
603 }
604 int32_t closeRet = fclose(fp);
605 if (closeRet != 0) {
606 AUDIO_ERR_LOG("something wrong when fclose! err:%{public}d", errno);
607 }
608 AUDIO_DEBUG_LOG("audio read dp name path: %{public}s, name:%{public}s",
609 path.c_str(), deviceName);
610
611 name = deviceName;
612 auto portPos = name.find(DEVICE_PORT);
613 if (portPos == std::string::npos) {
614 name.clear();
615 AUDIO_ERR_LOG("audio read dp name node device port not find, %{public}d", errno);
616 return ERROR;
617 }
618 name = name.substr(portPos + std::strlen(DEVICE_PORT));
619 name.erase(name.find_last_not_of('\n') + 1);
620 return SUCCESS;
621 }
622 } // namespace AudioStandard
623 } // namespace OHOS