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