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