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,char switchState)158 void AudioSocketThread::SetAudioPnpUevent(AudioEvent *audioEvent, char switchState)
159 {
160 if (audioEvent == nullptr) {
161 AUDIO_ERR_LOG("audioEvent is null!");
162 return;
163 }
164 static uint32_t h2wTypeLast = PNP_DEVICE_HEADSET;
165 switch (switchState) {
166 case REMOVE_AUDIO_DEVICE:
167 audioEvent->eventType = PNP_EVENT_DEVICE_REMOVE;
168 audioEvent->deviceType = h2wTypeLast;
169 break;
170 case ADD_DEVICE_HEADSET:
171 audioEvent->eventType = PNP_EVENT_DEVICE_ADD;
172 audioEvent->deviceType = PNP_DEVICE_HEADSET;
173 break;
174 case ADD_DEVICE_HEADSET_WITHOUT_MIC:
175 audioEvent->eventType = PNP_EVENT_DEVICE_ADD;
176 audioEvent->deviceType = PNP_DEVICE_HEADPHONE;
177 break;
178 case ADD_DEVICE_ADAPTER:
179 audioEvent->eventType = PNP_EVENT_DEVICE_ADD;
180 audioEvent->deviceType = PNP_DEVICE_ADAPTER_DEVICE;
181 break;
182 default:
183 audioEvent->eventType = PNP_EVENT_DEVICE_ADD;
184 audioEvent->deviceType = PNP_DEVICE_UNKNOWN;
185 break;
186 }
187 h2wTypeLast = audioEvent->deviceType;
188 }
189
SetAudioPnpServerEventValue(AudioEvent * audioEvent,struct AudioPnpUevent * audioPnpUevent)190 int32_t AudioSocketThread::SetAudioPnpServerEventValue(AudioEvent *audioEvent, struct AudioPnpUevent *audioPnpUevent)
191 {
192 if (audioEvent == nullptr) {
193 AUDIO_ERR_LOG("audioEvent is null!");
194 return ERROR;
195 }
196 if (strncmp(audioPnpUevent->subSystem, UEVENT_SUBSYSTEM_SWITCH, strlen(UEVENT_SUBSYSTEM_SWITCH)) == 0) {
197 if (strncmp(audioPnpUevent->switchName, UEVENT_SWITCH_NAME_H2W, strlen(UEVENT_SWITCH_NAME_H2W)) != 0) {
198 AUDIO_ERR_LOG("the switch name of 'h2w' not found!");
199 return ERROR;
200 }
201 AudioSocketThread::SetAudioPnpUevent(audioEvent, audioPnpUevent->switchState[0]);
202 audioEvent->name = audioPnpUevent->name;
203 audioEvent->address = audioPnpUevent->devName;
204 } else {
205 if (strncmp(audioPnpUevent->action, UEVENT_ACTION_CHANGE, strlen(UEVENT_ACTION_CHANGE)) != 0) {
206 return ERROR;
207 }
208 if (strstr(audioPnpUevent->name, UEVENT_NAME_HEADSET) == NULL) {
209 return ERROR;
210 }
211 if (strncmp(audioPnpUevent->devType, UEVENT_TYPE_EXTCON, strlen(UEVENT_TYPE_EXTCON)) != 0) {
212 return ERROR;
213 }
214 if (strstr(audioPnpUevent->state, UEVENT_STATE_ANALOG_HS0) != NULL) {
215 audioEvent->eventType = PNP_EVENT_DEVICE_REMOVE;
216 } else if (strstr(audioPnpUevent->state, UEVENT_STATE_ANALOG_HS1) != NULL) {
217 audioEvent->eventType = PNP_EVENT_DEVICE_ADD;
218 } else {
219 return ERROR;
220 }
221 audioEvent->deviceType = PNP_DEVICE_HEADSET;
222 }
223 return SUCCESS;
224 }
225
AudioAnahsDetectDevice(struct AudioPnpUevent * audioPnpUevent)226 int32_t AudioSocketThread::AudioAnahsDetectDevice(struct AudioPnpUevent *audioPnpUevent)
227 {
228 AudioEvent audioEvent;
229 if (audioPnpUevent == NULL) {
230 AUDIO_ERR_LOG("audioPnpUevent is null!");
231 return HDF_ERR_INVALID_PARAM;
232 }
233 if (SetAudioAnahsEventValue(&audioEvent, audioPnpUevent) != SUCCESS) {
234 return ERROR;
235 }
236
237 if (audioEvent.anahsName == audioSocketEvent_.anahsName) {
238 AUDIO_ERR_LOG("audio anahs device[%{public}u] state[%{public}u] not need flush !", audioEvent.deviceType,
239 audioEvent.eventType);
240 return SUCCESS;
241 }
242 audioSocketEvent_.anahsName = audioEvent.anahsName;
243 return SUCCESS;
244 }
245
AudioAnalogHeadsetDetectDevice(struct AudioPnpUevent * audioPnpUevent)246 int32_t AudioSocketThread::AudioAnalogHeadsetDetectDevice(struct AudioPnpUevent *audioPnpUevent)
247 {
248 AudioEvent audioEvent;
249 if (audioPnpUevent == NULL) {
250 AUDIO_ERR_LOG("audioPnpUevent is null!");
251 return HDF_ERR_INVALID_PARAM;
252 }
253
254 if (SetAudioPnpServerEventValue(&audioEvent, audioPnpUevent) != SUCCESS) {
255 return ERROR;
256 }
257 AUDIO_DEBUG_LOG("audio analog [%{public}s][%{public}s]",
258 audioEvent.deviceType == PNP_DEVICE_HEADSET ? "headset" : "headphone",
259 audioEvent.eventType == PNP_EVENT_DEVICE_ADD ? "add" : "removed");
260
261 if (!IsUpdatePnpDeviceState(&audioEvent)) {
262 AUDIO_ERR_LOG("audio analog device[%{public}u] state[%{public}u] not need flush !", audioEvent.deviceType,
263 audioEvent.eventType);
264 return SUCCESS;
265 }
266 UpdatePnpDeviceState(&audioEvent);
267 return SUCCESS;
268 }
269
AudioNnDetectDevice(struct AudioPnpUevent * audioPnpUevent)270 int32_t AudioSocketThread::AudioNnDetectDevice(struct AudioPnpUevent *audioPnpUevent)
271 {
272 if (audioPnpUevent == NULL) {
273 return HDF_ERR_INVALID_PARAM;
274 }
275
276 if ((strcmp(audioPnpUevent->action, "change") != 0) ||
277 (strncmp(audioPnpUevent->name, "send_nn_state", strlen("send_nn_state")) != 0)) {
278 return HDF_ERR_INVALID_PARAM;
279 }
280
281 std::string ueventStr = audioPnpUevent->name;
282 auto state = ueventStr.substr(ueventStr.find("send_nn_state") + strlen("send_nn_state") + 1);
283 int32_t nnState;
284 switch (atoi(state.c_str())) {
285 case STATE_NOT_SUPPORTED:
286 nnState = STATE_NOT_SUPPORTED;
287 break;
288 case STATE_NN_OFF:
289 nnState = STATE_NN_OFF;
290 break;
291 case STATE_NN_ON:
292 nnState = STATE_NN_ON;
293 break;
294 default:
295 AUDIO_ERR_LOG("NN state is invalid");
296 return HDF_ERR_INVALID_PARAM;
297 }
298
299 // callback of bluetooth
300 auto handle = DelayedSingleton<AudioPolicyServerHandler>::GetInstance();
301 if (handle == nullptr) {
302 AUDIO_ERR_LOG("get AudioPolicyServerHandler instance failed");
303 return HDF_ERR_INVALID_PARAM;
304 }
305 bool ret = handle->SendNnStateChangeCallback(nnState);
306 AUDIO_INFO_LOG("NN state change callback ret is [%{public}d]", ret);
307 return ret;
308 }
309
AudioDpDetectDevice(struct AudioPnpUevent * audioPnpUevent)310 int32_t AudioSocketThread::AudioDpDetectDevice(struct AudioPnpUevent *audioPnpUevent)
311 {
312 AudioEvent audioEvent = {0};
313 if (audioPnpUevent == NULL) {
314 return HDF_ERR_INVALID_PARAM;
315 }
316 if ((strcmp(audioPnpUevent->subSystem, "switch") != 0) ||
317 (strstr(audioPnpUevent->switchName, "hdmi_audio") == NULL) ||
318 (strcmp(audioPnpUevent->action, "change") != 0)) {
319 return HDF_ERR_INVALID_PARAM;
320 }
321
322 if (strcmp(audioPnpUevent->switchState, "1") == 0) {
323 audioEvent.eventType = PNP_EVENT_DEVICE_ADD;
324 } else if (strcmp(audioPnpUevent->switchState, "0") == 0) {
325 audioEvent.eventType = PNP_EVENT_DEVICE_REMOVE;
326 } else {
327 AUDIO_ERR_LOG("audio dp device [%{public}d]", audioEvent.eventType);
328 return ERROR;
329 }
330 audioEvent.deviceType = PNP_DEVICE_DP_DEVICE;
331
332 std::string switchNameStr = audioPnpUevent->switchName;
333
334 auto portBegin = switchNameStr.find("device_port=");
335 if (portBegin != switchNameStr.npos) {
336 audioEvent.name = switchNameStr.substr(portBegin + std::strlen("device_port="),
337 switchNameStr.length() - portBegin - std::strlen("device_port="));
338 }
339
340 auto addressBegin = switchNameStr.find("hdmi_audio");
341 auto addressEnd = switchNameStr.find_first_of("device_port", portBegin);
342 if (addressEnd != switchNameStr.npos) {
343 std::string portId = switchNameStr.substr(addressBegin + std::strlen("hdmi_audio"),
344 addressEnd - addressBegin - std::strlen("hdmi_audio")-1);
345 audioEvent.address = portId;
346 AUDIO_INFO_LOG("audio dp device portId:[%{public}s]", portId.c_str());
347 }
348
349 if (audioEvent.address.empty()) {
350 audioEvent.address = '0';
351 }
352 AUDIO_INFO_LOG("audio dp device [%{public}s]", audioEvent.eventType == PNP_EVENT_DEVICE_ADD ? "add" : "removed");
353
354 if (!IsUpdatePnpDeviceState(&audioEvent)) {
355 AUDIO_ERR_LOG("audio usb device[%{public}u] state[%{public}u] not need flush !", audioEvent.deviceType,
356 audioEvent.eventType);
357 return SUCCESS;
358 }
359 UpdatePnpDeviceState(&audioEvent);
360 return SUCCESS;
361 }
362
AudioMicBlockDevice(struct AudioPnpUevent * audioPnpUevent)363 int32_t AudioSocketThread::AudioMicBlockDevice(struct AudioPnpUevent *audioPnpUevent)
364 {
365 if (audioPnpUevent == nullptr) {
366 AUDIO_ERR_LOG("mic blocked audioPnpUevent is null");
367 return HDF_ERR_INVALID_PARAM;
368 }
369 AudioEvent audioEvent = {0};
370 if (strncmp(audioPnpUevent->name, "mic_blocked", strlen("mic_blocked")) == 0) {
371 audioEvent.eventType = PNP_EVENT_MIC_BLOCKED;
372 } else if (strncmp(audioPnpUevent->name, "mic_un_blocked", strlen("mic_un_blocked")) == 0) {
373 audioEvent.eventType = PNP_EVENT_MIC_UNBLOCKED;
374 } else {
375 return HDF_ERR_INVALID_PARAM;
376 }
377 audioEvent.deviceType = PNP_DEVICE_MIC;
378
379 AUDIO_INFO_LOG("mic blocked uevent info recv: %{public}s", audioPnpUevent->name);
380 UpdatePnpDeviceState(&audioEvent);
381 return SUCCESS;
382 }
383
AudioHDMIDetectDevice(struct AudioPnpUevent * audioPnpUevent)384 int32_t AudioSocketThread::AudioHDMIDetectDevice(struct AudioPnpUevent *audioPnpUevent)
385 {
386 AudioEvent audioEvent = {0};
387 if (audioPnpUevent == NULL) {
388 return HDF_ERR_INVALID_PARAM;
389 }
390 if ((strcmp(audioPnpUevent->subSystem, "switch") != 0) ||
391 (strstr(audioPnpUevent->switchName, "hdmi_mipi_audio") == NULL) ||
392 (strcmp(audioPnpUevent->action, "change") != 0)) {
393 AUDIO_DEBUG_LOG("AudioHDMIDetectDevice fail");
394 return HDF_ERR_INVALID_PARAM;
395 }
396
397 if (strcmp(audioPnpUevent->switchState, "1") == 0) {
398 audioEvent.eventType = PNP_EVENT_DEVICE_ADD;
399 } else if (strcmp(audioPnpUevent->switchState, "0") == 0) {
400 audioEvent.eventType = PNP_EVENT_DEVICE_REMOVE;
401 } else {
402 AUDIO_ERR_LOG("audio hdmi device [%{public}d]", audioEvent.eventType);
403 return ERROR;
404 }
405 audioEvent.deviceType = PNP_DEVICE_HDMI_DEVICE;
406
407 std::string switchNameStr = audioPnpUevent->switchName;
408
409 auto portBegin = switchNameStr.find("device_port=");
410 if (portBegin != switchNameStr.npos) {
411 audioEvent.name = switchNameStr.substr(portBegin + std::strlen("device_port="),
412 switchNameStr.length() - portBegin - std::strlen("device_port="));
413 }
414
415 auto addressBegin = switchNameStr.find("hdmi_mipi_audio");
416 auto addressEnd = switchNameStr.find_first_of("device_port", portBegin);
417 if (addressEnd != switchNameStr.npos) {
418 std::string portId = switchNameStr.substr(addressBegin + std::strlen("hdmi_mipi_audio"),
419 addressEnd - addressBegin - std::strlen("hdmi_mipi_audio")-1);
420 audioEvent.address = portId;
421 }
422
423 if (audioEvent.address.empty()) {
424 audioEvent.address = '0';
425 }
426 AUDIO_INFO_LOG("audio hdmi device [%{public}s]", audioEvent.eventType == PNP_EVENT_DEVICE_ADD ? "add" : "removed");
427
428 if (!IsUpdatePnpDeviceState(&audioEvent)) {
429 AUDIO_ERR_LOG("audio device[%{public}u] state[%{public}u] not need flush !", audioEvent.deviceType,
430 audioEvent.eventType);
431 return SUCCESS;
432 }
433 UpdatePnpDeviceState(&audioEvent);
434 return SUCCESS;
435 }
436
AudioPnpUeventParse(const char * msg,const ssize_t strLength)437 bool AudioSocketThread::AudioPnpUeventParse(const char *msg, const ssize_t strLength)
438 {
439 struct AudioPnpUevent audioPnpUevent = {"", "", "", "", "", "", "", "", "", ""};
440
441 if (strncmp(msg, "libudev", strlen("libudev")) == 0) {
442 return false;
443 }
444
445 if (strLength > UEVENT_MSG_LEN + 1) {
446 AUDIO_ERR_LOG("strLength > UEVENT_MSG_LEN + 1");
447 return false;
448 }
449 AUDIO_DEBUG_LOG("Param strLength: %{public}zu msg:[%{public}s] len:[%{public}zu]", strLength, msg, strlen(msg));
450 for (const char *msgTmp = msg; msgTmp < (msg + strLength);) {
451 if (*msgTmp == '\0') {
452 msgTmp++;
453 continue;
454 }
455 AUDIO_DEBUG_LOG("Param msgTmp:[%{private}s] len:[%{public}zu]", msgTmp, strlen(msgTmp));
456 const char *arrStrTmp[UEVENT_ARR_SIZE] = {
457 UEVENT_ACTION, UEVENT_DEV_NAME, UEVENT_NAME, UEVENT_STATE, UEVENT_DEVTYPE,
458 UEVENT_SUBSYSTEM, UEVENT_SWITCH_NAME, UEVENT_SWITCH_STATE, UEVENT_HDI_NAME,
459 UEVENT_ANAHS
460 };
461 const char **arrVarTmp[UEVENT_ARR_SIZE] = {
462 &audioPnpUevent.action, &audioPnpUevent.devName, &audioPnpUevent.name,
463 &audioPnpUevent.state, &audioPnpUevent.devType, &audioPnpUevent.subSystem,
464 &audioPnpUevent.switchName, &audioPnpUevent.switchState, &audioPnpUevent.hidName,
465 &audioPnpUevent.anahsName
466 };
467 for (int count = 0; count < UEVENT_ARR_SIZE; count++) {
468 if (strncmp(msgTmp, arrStrTmp[count], strlen(arrStrTmp[count])) == 0) {
469 msgTmp += strlen(arrStrTmp[count]);
470 *arrVarTmp[count] = msgTmp;
471 break;
472 }
473 }
474 msgTmp += strlen(msgTmp) + 1;
475 }
476
477 if ((AudioAnalogHeadsetDetectDevice(&audioPnpUevent) == SUCCESS) ||
478 (AudioHDMIDetectDevice(&audioPnpUevent) == SUCCESS) ||
479 (AudioDpDetectDevice(&audioPnpUevent) == SUCCESS) ||
480 (AudioAnahsDetectDevice(&audioPnpUevent) == SUCCESS) ||
481 (AudioNnDetectDevice(&audioPnpUevent) == SUCCESS) ||
482 (AudioMicBlockDevice(&audioPnpUevent) == SUCCESS)) {
483 return true;
484 }
485
486 return false;
487 }
488
DetectAnalogHeadsetState(AudioEvent * audioEvent)489 int32_t AudioSocketThread::DetectAnalogHeadsetState(AudioEvent *audioEvent)
490 {
491 if (audioEvent == nullptr) {
492 AUDIO_ERR_LOG("audioEvent is null!");
493 return ERROR;
494 }
495 int8_t state = 0;
496 FILE *fp = fopen(SWITCH_STATE_PATH, "r");
497 if (fp == NULL) {
498 AUDIO_ERR_LOG("audio open switch state node fail, %{public}d", errno);
499 return HDF_ERR_INVALID_PARAM;
500 }
501
502 size_t ret = fread(&state, STATE_PATH_ITEM_SIZE, STATE_PATH_ITEM_SIZE, fp);
503 if (ret == 0) {
504 fclose(fp);
505 AUDIO_ERR_LOG("audio read switch state node fail, %{public}d", errno);
506 return ERROR;
507 }
508
509 AudioSocketThread::SetAudioPnpUevent(audioEvent, state);
510
511 fclose(fp);
512 return SUCCESS;
513 }
514
UpdateDeviceState(AudioEvent audioEvent)515 void AudioSocketThread::UpdateDeviceState(AudioEvent audioEvent)
516 {
517 char pnpInfo[AUDIO_EVENT_INFO_LEN_MAX] = {0};
518 int32_t ret;
519 if (!IsUpdatePnpDeviceState(&audioEvent)) {
520 AUDIO_ERR_LOG("audio first pnp device[%{public}u] state[%{public}u] not need flush !", audioEvent.deviceType,
521 audioEvent.eventType);
522 return;
523 }
524 ret = snprintf_s(pnpInfo, AUDIO_EVENT_INFO_LEN_MAX, AUDIO_EVENT_INFO_LEN_MAX - 1, "EVENT_TYPE=%u;DEVICE_TYPE=%u",
525 audioEvent.eventType, audioEvent.deviceType);
526 if (ret < 0) {
527 AUDIO_ERR_LOG("snprintf_s fail!");
528 return;
529 }
530
531 UpdatePnpDeviceState(&audioEvent);
532 return;
533 }
534
DetectDPState(AudioEvent * audioEvent)535 int32_t AudioSocketThread::DetectDPState(AudioEvent *audioEvent)
536 {
537 for (size_t i = 0; i <= DP_PORT_COUNT; ++i) {
538 std::string statePath = DP_PATH;
539 std::string namePath = DP_PATH;
540
541 if (i == 0) {
542 statePath.append("/state");
543 namePath.append("/name");
544 } else {
545 statePath.append(std::to_string(i) + "/state");
546 namePath.append(std::to_string(i) + "/name");
547 }
548
549 int32_t ret = ReadAndScanDpState(statePath, audioEvent->eventType);
550 if (ret != SUCCESS || audioEvent->eventType != PNP_EVENT_DEVICE_ADD) continue;
551
552 ret = ReadAndScanDpName(namePath, audioEvent->name);
553 if (ret != SUCCESS) continue;
554
555 audioEvent->deviceType = PNP_DEVICE_DP_DEVICE;
556 audioEvent->address = std::to_string(i);
557
558 AUDIO_INFO_LOG("dp device reconnect when server start");
559 return SUCCESS;
560 }
561 return ERROR;
562 }
563
ReadAndScanDpState(const std::string & path,uint32_t & eventType)564 int32_t AudioSocketThread::ReadAndScanDpState(const std::string &path, uint32_t &eventType)
565 {
566 int8_t state = 0;
567
568 FILE *fp = fopen(path.c_str(), "r");
569 if (fp == nullptr) {
570 AUDIO_ERR_LOG("audio open dp state node fail, %{public}d", errno);
571 return HDF_ERR_INVALID_PARAM;
572 }
573 size_t ret = fread(&state, STATE_PATH_ITEM_SIZE, STATE_PATH_ITEM_SIZE, fp);
574 if (ret == 0) {
575 fclose(fp);
576 AUDIO_ERR_LOG("audio read dp state node fail, %{public}d", errno);
577 return ERROR;
578 }
579 int32_t closeRet = fclose(fp);
580 if (closeRet != 0) {
581 AUDIO_ERR_LOG("something wrong when fclose! err:%{public}d", errno);
582 }
583
584 if (state == '1') {
585 eventType = PNP_EVENT_DEVICE_ADD;
586 } else if (state == '0') {
587 eventType = PNP_EVENT_DEVICE_REMOVE;
588 return ERROR;
589 } else {
590 AUDIO_ERR_LOG("audio dp device [%{public}d]", eventType);
591 return ERROR;
592 }
593 AUDIO_DEBUG_LOG("audio read dp state path: %{public}s, event type: %{public}d",
594 path.c_str(), eventType);
595 return SUCCESS;
596 }
597
ReadAndScanDpName(const std::string & path,std::string & name)598 int32_t AudioSocketThread::ReadAndScanDpName(const std::string &path, std::string &name)
599 {
600 char deviceName[AUDIO_PNP_INFO_LEN_MAX];
601
602 FILE *fp = fopen(path.c_str(), "r");
603 if (fp == nullptr) {
604 AUDIO_ERR_LOG("audio open dp name node fail, %{public}d", errno);
605 return HDF_ERR_INVALID_PARAM;
606 }
607 size_t ret = fread(&deviceName, STATE_PATH_ITEM_SIZE, AUDIO_PNP_INFO_LEN_MAX, fp);
608 if (ret == 0) {
609 fclose(fp);
610 AUDIO_ERR_LOG("audio read dp name node fail, %{public}d", errno);
611 return ERROR;
612 }
613 int32_t closeRet = fclose(fp);
614 if (closeRet != 0) {
615 AUDIO_ERR_LOG("something wrong when fclose! err:%{public}d", errno);
616 }
617 AUDIO_DEBUG_LOG("audio read dp name path: %{public}s, name:%{public}s",
618 path.c_str(), deviceName);
619
620 name = deviceName;
621 auto portPos = name.find(DEVICE_PORT);
622 if (portPos == std::string::npos) {
623 name.clear();
624 AUDIO_ERR_LOG("audio read dp name node device port not find, %{public}d", errno);
625 return ERROR;
626 }
627 name = name.substr(portPos + std::strlen(DEVICE_PORT));
628 name.erase(name.find_last_not_of('\n') + 1);
629 return SUCCESS;
630 }
631 } // namespace AudioStandard
632 } // namespace OHOS