• 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,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