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