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