1 /*
2 * Copyright (c) 2025 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 "AudioStreamMonitor"
17 #endif
18
19 #include "audio_stream_monitor.h"
20 #include "audio_errors.h"
21 #include "audio_renderer_log.h"
22 #include "audio_utils.h"
23 #include "media_monitor_manager.h"
24
25 namespace OHOS {
26 namespace AudioStandard {
27 namespace {
28 const int32_t CHECK_ALL_RENDER_UID = -1;
29 const int32_t MAX_REGISTER_CALLBACK_NUM = 30;
30 }
31
GetInstance()32 AudioStreamMonitor& AudioStreamMonitor::GetInstance()
33 {
34 static AudioStreamMonitor monitor;
35 return monitor;
36 }
37
HasRegistered(const int32_t pid,const int32_t callbackId)38 bool AudioStreamMonitor::HasRegistered(const int32_t pid, const int32_t callbackId)
39 {
40 auto iter = registerInfo_.find(std::make_pair(pid, callbackId));
41 if (iter != registerInfo_.end()) {
42 AUDIO_INFO_LOG("Monitor has registered, pid = %{public}d, callbackId = %{public}d",
43 pid, callbackId);
44 return true;
45 }
46 AUDIO_INFO_LOG("Monitor not register, pid = %{public}d, callbackId = %{public}d", pid, callbackId);
47 return false;
48 }
49
RegisterAudioRendererDataTransferStateListener(const DataTransferMonitorParam & param,const int32_t pid,const int32_t callbackId)50 int32_t AudioStreamMonitor::RegisterAudioRendererDataTransferStateListener(
51 const DataTransferMonitorParam ¶m, const int32_t pid, const int32_t callbackId)
52 {
53 std::lock_guard<std::mutex> lock(regStatusMutex_);
54 AUDIO_INFO_LOG("Start register, pid = %{public}d, callbackId = %{public}d", pid, callbackId);
55 if (registerInfo_.size() > MAX_REGISTER_CALLBACK_NUM) {
56 AUDIO_ERR_LOG("Audio stream register num exceed max");
57 return ERR_AUDIO_STREAM_REGISTER_EXCEED_MAX;
58 }
59 if (HasRegistered(pid, callbackId)) {
60 AUDIO_ERR_LOG("Audio stream register repeat");
61 return ERR_AUDIO_STREAM_REGISTER_REPEAT;
62 }
63
64 std::pair<int32_t, int32_t> pairData = std::make_pair(pid, callbackId);
65 registerInfo_[pairData] = param;
66 AUDIO_INFO_LOG("Register audio stream monitor success");
67 for (auto &item : audioStreamCheckers_) {
68 if (item.second->GetAppUid() == param.clientUID || param.clientUID == CHECK_ALL_RENDER_UID) {
69 AUDIO_INFO_LOG("Find and init checker, sessionId = %{public}u, uid = %{public}d",
70 item.first, param.clientUID);
71 item.second->InitChecker(param, pid, callbackId);
72 }
73 }
74 return SUCCESS;
75 }
76
UnregisterAudioRendererDataTransferStateListener(const int32_t pid,const int32_t callbackId)77 int32_t AudioStreamMonitor::UnregisterAudioRendererDataTransferStateListener(
78 const int32_t pid, const int32_t callbackId)
79 {
80 std::lock_guard<std::mutex> lock(regStatusMutex_);
81 AUDIO_INFO_LOG("Start unregister, pid = %{public}d, callbackId = %{public}d", pid, callbackId);
82 for (auto iter = registerInfo_.begin(); iter != registerInfo_.end();) {
83 if (iter->first.first == pid && iter->first.second == callbackId) {
84 AUDIO_INFO_LOG("Unregister callback seccess");
85 iter = registerInfo_.erase(iter);
86 } else {
87 iter++;
88 }
89 }
90 for (auto iter = audioStreamCheckers_.begin(); iter != audioStreamCheckers_.end(); iter++) {
91 iter->second->DeleteCheckerPara(pid, callbackId);
92 }
93 return SUCCESS;
94 }
95
OnCallback(int32_t pid,int32_t callbackId,const AudioRendererDataTransferStateChangeInfo & info)96 void AudioStreamMonitor::OnCallback(int32_t pid, int32_t callbackId,
97 const AudioRendererDataTransferStateChangeInfo &info)
98 {
99 std::lock_guard<std::mutex> lock(regStatusMutex_);
100 if (audioServer_ == nullptr) {
101 return;
102 }
103 AUDIO_INFO_LOG("pid = %{public}d, callbackid = %{public}d, sessionId = %{public}d, type = %{public}d",
104 pid, callbackId, info.sessionId, info.stateChangeType);
105 audioServer_->OnDataTransferStateChange(pid, callbackId, info);
106 }
107
OnMuteCallback(const int32_t & pid,const int32_t & callbackId,const int32_t & uid,const uint32_t & sessionId,const bool & isMuted)108 void AudioStreamMonitor::OnMuteCallback(const int32_t &pid, const int32_t &callbackId,
109 const int32_t &uid, const uint32_t &sessionId, const bool &isMuted)
110 {
111 std::lock_guard<std::mutex> lock(regStatusMutex_);
112 if (audioServer_ == nullptr) {
113 return;
114 }
115 AUDIO_INFO_LOG("pid = %{public}d, uid = %{public}d, sessionId = %{public}d, isMuted = %{public}d",
116 pid, uid, sessionId, isMuted);
117 audioServer_->OnMuteStateChange(pid, callbackId, uid, sessionId, isMuted);
118 }
119
SetAudioServerPtr(DataTransferStateChangeCallbackForMonitor * ptr)120 void AudioStreamMonitor::SetAudioServerPtr(DataTransferStateChangeCallbackForMonitor *ptr)
121 {
122 std::lock_guard<std::mutex> lock(regStatusMutex_);
123 audioServer_ = ptr;
124 }
125
AddCheckForMonitor(uint32_t sessionId,std::shared_ptr<AudioStreamChecker> & checker)126 void AudioStreamMonitor::AddCheckForMonitor(uint32_t sessionId, std::shared_ptr<AudioStreamChecker> &checker)
127 {
128 std::lock_guard<std::mutex> lock(regStatusMutex_);
129 AUDIO_INFO_LOG("Add checker for monitor, sessionId = %{public}u", sessionId);
130 auto iter = audioStreamCheckers_.find(sessionId);
131 if (iter == audioStreamCheckers_.end()) {
132 audioStreamCheckers_[sessionId] = checker;
133 AUDIO_INFO_LOG("Add checker for monitor success, uid = %{public}d", checker->GetAppUid());
134 }
135 for (auto item : registerInfo_) {
136 if (item.second.clientUID == checker->GetAppUid() || item.second.clientUID == CHECK_ALL_RENDER_UID) {
137 AUDIO_INFO_LOG("Find register, need init checker, uid = %{public}d", item.second.clientUID);
138 checker->InitChecker(item.second, item.first.first, item.first.second);
139 }
140 }
141 }
142
OnCallbackAppDied(const int32_t pid)143 void AudioStreamMonitor::OnCallbackAppDied(const int32_t pid)
144 {
145 std::lock_guard<std::mutex> lock(regStatusMutex_);
146 AUDIO_INFO_LOG("On callback app died, pid = %{public}d", pid);
147 for (auto iter = registerInfo_.begin(); iter != registerInfo_.end();) {
148 if (iter->first.first == pid) {
149 AUDIO_INFO_LOG("erase registerInfo seccess by pid");
150 iter = registerInfo_.erase(iter);
151 } else {
152 iter++;
153 }
154 }
155 for (auto iter = audioStreamCheckers_.begin(); iter != audioStreamCheckers_.end(); iter++) {
156 iter->second->OnRemoteAppDied(pid);
157 }
158 }
159
DeleteCheckForMonitor(uint32_t sessionId)160 void AudioStreamMonitor::DeleteCheckForMonitor(uint32_t sessionId)
161 {
162 std::lock_guard<std::mutex> lock(regStatusMutex_);
163 for (auto iter = audioStreamCheckers_.begin(); iter != audioStreamCheckers_.end();) {
164 if (iter->first == sessionId) {
165 AUDIO_INFO_LOG("Find checker and delete, sessionId = %{public}u", sessionId);
166 iter->second->StopCheckStreamThread();
167 iter = audioStreamCheckers_.erase(iter);
168 } else {
169 iter++;
170 }
171 }
172 AUDIO_INFO_LOG("Can not find checker, sessionId = %{public}u", sessionId);
173 }
174
ReportStreamFreezen(int64_t intervalTime)175 void AudioStreamMonitor::ReportStreamFreezen(int64_t intervalTime)
176 {
177 // To do report
178 }
179
NotifyAppStateChange(const int32_t uid,bool isBackground)180 void AudioStreamMonitor::NotifyAppStateChange(const int32_t uid, bool isBackground)
181 {
182 std::lock_guard<std::mutex> lock(regStatusMutex_);
183 for (auto iter = audioStreamCheckers_.begin(); iter != audioStreamCheckers_.end();) {
184 if (iter->second->GetAppUid() == uid) {
185 iter->second->UpdateAppState(isBackground);
186 }
187 iter++;
188 }
189 }
190
UpdateMonitorVolume(const uint32_t & sessionId,const float & volume)191 void AudioStreamMonitor::UpdateMonitorVolume(const uint32_t &sessionId, const float &volume)
192 {
193 std::lock_guard<std::mutex> lock(regStatusMutex_);
194 auto iter = audioStreamCheckers_.find(sessionId);
195 if (iter != audioStreamCheckers_.end()) {
196 iter->second->SetVolume(volume);
197 }
198 }
199 }
200 }