• 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 "AudioPnpServer"
17 #endif
18 
19 #include "audio_pnp_server.h"
20 
21 #include <poll.h>
22 #include "securec.h"
23 #include "osal_time.h"
24 #include "audio_utils.h"
25 #include "audio_errors.h"
26 #include "audio_input_thread.h"
27 #include "audio_policy_log.h"
28 #include "audio_socket_thread.h"
29 
30 using namespace std;
31 namespace OHOS {
32 namespace AudioStandard {
33 static bool g_socketRunThread = false;
34 static bool g_inputRunThread = false;
35 
GetAudioEventInfo(const AudioEvent audioEvent)36 static std::string GetAudioEventInfo(const AudioEvent audioEvent)
37 {
38     int32_t ret;
39     char event[AUDIO_PNP_INFO_LEN_MAX] = {0};
40     if ((audioEvent.eventType == PNP_EVENT_UNKNOWN && audioEvent.anahsName == "") ||
41         (audioEvent.deviceType == PNP_DEVICE_UNKNOWN && audioEvent.anahsName == "")) {
42         AUDIO_ERR_LOG("audio event is not updated");
43         return event;
44     }
45     ret = snprintf_s(event, AUDIO_PNP_INFO_LEN_MAX, AUDIO_PNP_INFO_LEN_MAX - 1,
46         "EVENT_TYPE=%u;DEVICE_TYPE=%u;EVENT_NAME=%s;DEVICE_ADDRESS=%s;ANAHS_NAME=%s", audioEvent.eventType,
47         audioEvent.deviceType, audioEvent.name.c_str(), audioEvent.address.c_str(), audioEvent.anahsName.c_str());
48     if (ret < 0) {
49         AUDIO_ERR_LOG("snprintf_s failed");
50         return event;
51     }
52 
53     return event;
54 }
55 
~AudioPnpServer()56 AudioPnpServer::~AudioPnpServer()
57 {
58     AUDIO_INFO_LOG("~AudioPnpServer");
59     g_socketRunThread = false;
60     g_inputRunThread = false;
61 
62     if (socketThread_ && socketThread_->joinable()) {
63         socketThread_->detach();
64     }
65 
66     if (inputThread_ && inputThread_->joinable()) {
67         inputThread_->detach();
68     }
69 }
70 
init(void)71 bool AudioPnpServer::init(void)
72 {
73     AUDIO_INFO_LOG("Init");
74     g_socketRunThread = true;
75     g_inputRunThread = true;
76 
77     socketThread_ = std::make_unique<std::thread>([this] { this->OpenAndReadWithSocket(); });
78     pthread_setname_np(socketThread_->native_handle(), "OS_SocketEvent");
79     inputThread_ = std::make_unique<std::thread>([this] { this->OpenAndReadInput(); });
80     pthread_setname_np(inputThread_->native_handle(), "OS_InputEvent");
81     return true;
82 }
83 
RegisterPnpStatusListener(std::shared_ptr<AudioPnpDeviceChangeCallback> callback)84 int32_t AudioPnpServer::RegisterPnpStatusListener(std::shared_ptr<AudioPnpDeviceChangeCallback> callback)
85 {
86     AUDIO_INFO_LOG("Enter");
87     {
88         std::lock_guard<std::mutex> lock(pnpMutex_);
89         pnpCallback_ = callback;
90     }
91 
92     DetectAudioDevice();
93     return SUCCESS;
94 }
95 
UnRegisterPnpStatusListener()96 int32_t AudioPnpServer::UnRegisterPnpStatusListener()
97 {
98     std::lock_guard<std::mutex> lock(pnpMutex_);
99     pnpCallback_ = nullptr;
100     return SUCCESS;
101 }
102 
OnPnpDeviceStatusChanged(const std::string & info)103 void AudioPnpServer::OnPnpDeviceStatusChanged(const std::string &info)
104 {
105     std::lock_guard<std::mutex> lock(pnpMutex_);
106     if (pnpCallback_ != nullptr) {
107         pnpCallback_->OnPnpDeviceStatusChanged(info);
108     }
109 }
110 
OnMicrophoneBlocked(const std::string & info,AudioPnpServer & audioPnpServer)111 void MicrophoneBlocked::OnMicrophoneBlocked(const std::string &info, AudioPnpServer &audioPnpServer)
112 {
113     std::lock_guard<std::mutex> lock(audioPnpServer.pnpMutex_);
114     if (audioPnpServer.pnpCallback_ != nullptr) {
115         audioPnpServer.pnpCallback_->OnMicrophoneBlocked(info);
116     }
117 }
118 
OpenAndReadInput()119 void AudioPnpServer::OpenAndReadInput()
120 {
121     int32_t ret = -1;
122     int32_t status = AudioInputThread::AudioPnpInputOpen();
123     if (status != SUCCESS) {
124         return;
125     }
126 
127     do {
128         ret = AudioInputThread::AudioPnpInputPollAndRead();
129         if (ret != SUCCESS) {
130             AUDIO_ERR_LOG("[AudioPnpInputPollAndRead] failed");
131             return;
132         }
133         eventInfo_ = GetAudioEventInfo(AudioInputThread::audioInputEvent_);
134         CHECK_AND_RETURN_LOG(!eventInfo_.empty(), "invalid input info");
135         if (AudioSocketThread::audioSocketEvent_.eventType == PNP_EVENT_MIC_BLOCKED ||
136             AudioSocketThread::audioSocketEvent_.eventType == PNP_EVENT_MIC_UNBLOCKED) {
137             MicrophoneBlocked::GetInstance().OnMicrophoneBlocked(eventInfo_, GetAudioPnpServer());
138         } else {
139             OnPnpDeviceStatusChanged(eventInfo_);
140         }
141     } while (g_inputRunThread);
142     return;
143 }
144 
OpenAndReadWithSocket()145 void AudioPnpServer::OpenAndReadWithSocket()
146 {
147     ssize_t rcvLen;
148     int32_t socketFd = -1;
149     struct pollfd fd;
150     char msg[UEVENT_MSG_LEN + 1] = {0};
151 
152     int32_t ret = AudioSocketThread::AudioPnpUeventOpen(&socketFd);
153     if (ret != SUCCESS) {
154         AUDIO_ERR_LOG("open audio pnp socket failed");
155         return;
156     }
157 
158     fd.fd = socketFd;
159     fd.events = POLLIN | POLLERR;
160     fd.revents = 0;
161 
162     while (g_socketRunThread) {
163         if (poll(&fd, 1, -1) <= 0) {
164             AUDIO_ERR_LOG("audio event poll fail %{public}d", errno);
165             OsalMSleep(UEVENT_POLL_WAIT_TIME);
166             continue;
167         }
168 
169         if (((uint32_t)fd.revents & (POLLIN | POLLERR)) != 0) {
170             memset_s(&msg, sizeof(msg), 0, sizeof(msg));
171             rcvLen = AudioSocketThread::AudioPnpReadUeventMsg(socketFd, msg, UEVENT_MSG_LEN);
172             if (rcvLen <= 0) {
173                 continue;
174             }
175             bool status = AudioSocketThread::AudioPnpUeventParse(msg, rcvLen);
176             if (!status) {
177                 continue;
178             }
179             eventInfo_ = GetAudioEventInfo(AudioSocketThread::audioSocketEvent_);
180             CHECK_AND_RETURN_LOG(!eventInfo_.empty(), "invalid socket info");
181             if (AudioSocketThread::audioSocketEvent_.eventType == PNP_EVENT_MIC_BLOCKED ||
182                 AudioSocketThread::audioSocketEvent_.eventType == PNP_EVENT_MIC_UNBLOCKED) {
183                 MicrophoneBlocked::GetInstance().OnMicrophoneBlocked(eventInfo_, GetAudioPnpServer());
184             } else {
185                 OnPnpDeviceStatusChanged(eventInfo_);
186             }
187         }
188     }
189     CloseFd(socketFd);
190     return;
191 }
192 
DetectAudioDevice()193 void AudioPnpServer::DetectAudioDevice()
194 {
195     AUDIO_INFO_LOG("Enter");
196     int32_t ret;
197     AudioEvent audioEvent = {0};
198 
199     ret = AudioSocketThread::DetectAnalogHeadsetState(&audioEvent);
200     if ((ret == SUCCESS) && (audioEvent.eventType == AUDIO_DEVICE_ADD)) {
201         AUDIO_INFO_LOG("audio detect analog headset");
202         AudioSocketThread::UpdateDeviceState(audioEvent);
203 
204         eventInfo_ = GetAudioEventInfo(AudioSocketThread::audioSocketEvent_);
205         CHECK_AND_RETURN_LOG(!eventInfo_.empty(), "invalid detect info");
206         OnPnpDeviceStatusChanged(eventInfo_);
207         return;
208     }
209 
210     DetectAudioDpDevice();
211     AUDIO_INFO_LOG("Done");
212 }
213 
DetectAudioDpDevice()214 void AudioPnpServer::DetectAudioDpDevice()
215 {
216     AudioEvent audioEvent = {0};
217     int32_t ret = AudioSocketThread::DetectDPState(&audioEvent);
218     if ((ret == SUCCESS) && (audioEvent.eventType == AUDIO_DEVICE_ADD)) {
219         AUDIO_INFO_LOG("audio detect dp");
220         AudioSocketThread::UpdateDeviceState(audioEvent);
221         eventInfo_ = GetAudioEventInfo(AudioSocketThread::audioSocketEvent_);
222         CHECK_AND_RETURN_LOG(!eventInfo_.empty(), "invalid detect info");
223         OnPnpDeviceStatusChanged(eventInfo_);
224     }
225 }
226 
StopPnpServer()227 void AudioPnpServer::StopPnpServer()
228 {
229     g_socketRunThread = false;
230     g_inputRunThread = false;
231     if (socketThread_ && socketThread_->joinable()) {
232         socketThread_->detach();
233     }
234 
235     if (inputThread_ && inputThread_->joinable()) {
236         inputThread_->detach();
237     }
238 }
239 } // namespace AudioStandard
240 } // namespace OHOS
241