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