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 thread th([this] { DetectAudioDevice(); });
93 pthread_setname_np(th.native_handle(), "OS_DET_AUD_DEV");
94 th.detach();
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 | POLLERR)) != 0) {
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
DetectAudioDevice()195 void AudioPnpServer::DetectAudioDevice()
196 {
197 AUDIO_INFO_LOG("Enter");
198 int32_t ret;
199 AudioEvent audioEvent = {0};
200
201 ret = AudioSocketThread::DetectAnalogHeadsetState(&audioEvent);
202 if ((ret == SUCCESS) && (audioEvent.eventType == AUDIO_DEVICE_ADD)) {
203 AUDIO_INFO_LOG("audio detect analog headset");
204 AudioSocketThread::UpdateDeviceState(audioEvent);
205
206 eventInfo_ = GetAudioEventInfo(AudioSocketThread::audioSocketEvent_);
207 CHECK_AND_RETURN_LOG(!eventInfo_.empty(), "invalid detect info");
208 OnPnpDeviceStatusChanged(eventInfo_);
209 return;
210 }
211
212 DetectAudioDpDevice();
213 AUDIO_INFO_LOG("Done");
214 }
215
DetectAudioDpDevice()216 void AudioPnpServer::DetectAudioDpDevice()
217 {
218 AudioEvent audioEvent = {0};
219 int32_t ret = AudioSocketThread::DetectDPState(&audioEvent);
220 if ((ret == SUCCESS) && (audioEvent.eventType == AUDIO_DEVICE_ADD)) {
221 AUDIO_INFO_LOG("audio detect dp");
222 AudioSocketThread::UpdateDeviceState(audioEvent);
223 eventInfo_ = GetAudioEventInfo(AudioSocketThread::audioSocketEvent_);
224 CHECK_AND_RETURN_LOG(!eventInfo_.empty(), "invalid detect info");
225 OnPnpDeviceStatusChanged(eventInfo_);
226 }
227 }
228
StopPnpServer()229 void AudioPnpServer::StopPnpServer()
230 {
231 g_socketRunThread = false;
232 g_inputRunThread = false;
233 if (socketThread_ && socketThread_->joinable()) {
234 socketThread_->detach();
235 }
236
237 if (inputThread_ && inputThread_->joinable()) {
238 inputThread_->detach();
239 }
240 }
241 } // namespace AudioStandard
242 } // namespace OHOS
243