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