• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 #ifdef RESSCHED_AUDIO_FRAMEWORK_ENABLE
16 #include "audio_observer.h"
17 
18 #include "res_sched_log.h"
19 #include "res_sched_mgr.h"
20 #include "res_type.h"
21 
22 namespace OHOS {
23 namespace ResourceSchedule {
24     static const pid_t PID_MIN = -1;
Init()25 void AudioObserver::Init()
26 {
27     std::vector<std::shared_ptr<AudioStandard::AudioRendererChangeInfo>> audioRendererChangeInfos;
28     AudioStandard::AudioStreamManager::GetInstance()->GetCurrentRendererChangeInfos(audioRendererChangeInfos);
29     OnRendererStateChange(audioRendererChangeInfos);
30 }
31 
MarshallingAudioRendererChangeInfo(const std::shared_ptr<AudioStandard::AudioRendererChangeInfo> & audioRendererChangeInfo,nlohmann::json & payload)32 void AudioObserver::MarshallingAudioRendererChangeInfo(
33     const std::shared_ptr<AudioStandard::AudioRendererChangeInfo> &audioRendererChangeInfo, nlohmann::json &payload)
34 {
35     if (audioRendererChangeInfo == nullptr) {
36         return;
37     }
38     payload["uid"] = std::to_string(audioRendererChangeInfo->clientUID);
39     payload["sessionId"] = std::to_string(audioRendererChangeInfo->sessionId);
40     payload["rendererState"] = static_cast<int32_t>(audioRendererChangeInfo->rendererState);
41     payload["pid"] = std::to_string(audioRendererChangeInfo->clientPid);
42     RESSCHED_LOGD("MarshallingAudioRendererChangeInfo, uid: %{public}d, pid: %{public}d",
43         audioRendererChangeInfo->clientUID, audioRendererChangeInfo->clientPid);
44     /* struct AudioRendererInfo */
45     payload["rendererInfo.contentType"] = static_cast<int32_t>(audioRendererChangeInfo->rendererInfo.contentType);
46     payload["rendererInfo.streamUsage"] = static_cast<int32_t>(audioRendererChangeInfo->rendererInfo.streamUsage);
47 }
48 
IsRenderStateChange(const std::shared_ptr<AudioStandard::AudioRendererChangeInfo> & info)49 bool AudioObserver::IsRenderStateChange(const std::shared_ptr<AudioStandard::AudioRendererChangeInfo>& info)
50 {
51     auto item = renderState_.find(info->sessionId);
52     if (item != renderState_.end()) {
53         return item->second != info->rendererState;
54     }
55     return true;
56 }
57 
OnRendererStateChange(const std::vector<std::shared_ptr<AudioStandard::AudioRendererChangeInfo>> & audioRendererChangeInfos)58 void AudioObserver::OnRendererStateChange(
59     const std::vector<std::shared_ptr<AudioStandard::AudioRendererChangeInfo>> &audioRendererChangeInfos)
60 {
61     std::unordered_set<int32_t> newRunningPid;
62     std::unordered_set<int32_t> newStopSessionPid;
63     for (const auto &audioRendererChangeInfo : audioRendererChangeInfos) {
64         RESSCHED_LOGD("enter AudioRenderStateObserver::OnRendererStateChange, state: %{public}d",
65             audioRendererChangeInfo->rendererState);
66         nlohmann::json payload;
67         MarshallingAudioRendererChangeInfo(audioRendererChangeInfo, payload);
68         if (IsRenderStateChange(audioRendererChangeInfo)) {
69             ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_AUDIO_RENDER_STATE_CHANGE,
70                 audioRendererChangeInfo->rendererState, payload);
71         }
72         HandleInnerAudioStateChange(audioRendererChangeInfo, newRunningPid, newStopSessionPid);
73     }
74     renderState_.clear();
75     for (const auto &audioRendererChangeInfo : audioRendererChangeInfos) {
76         renderState_[audioRendererChangeInfo->sessionId] = audioRendererChangeInfo->rendererState;
77     }
78     HandleStartAudioStateEvent(newRunningPid);
79     HandleStopAudioStateEvent(newStopSessionPid);
80 }
81 
OnRingerModeUpdated(const AudioStandard::AudioRingerMode & ringerMode)82 void AudioObserver::OnRingerModeUpdated(const AudioStandard::AudioRingerMode &ringerMode)
83 {
84     if (ringerMode != mode_) {
85         RESSCHED_LOGI("enter AudioRingModeObserver::OnRingerModeUpdated, ringerMode: %{public}d", ringerMode);
86         mode_ = ringerMode;
87         const nlohmann::json payload = nlohmann::json::object();
88         ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_AUDIO_RING_MODE_CHANGE, ringerMode, payload);
89     }
90 }
91 
OnVolumeKeyEvent(AudioStandard::VolumeEvent volumeEvent)92 void AudioObserver::OnVolumeKeyEvent(AudioStandard::VolumeEvent volumeEvent)
93 {
94     RESSCHED_LOGI("enter AudioVolumeKeyObserver::OnVolumeKeyEvent, streamType: %{public}d, volumeLevel: %{public}d",
95         volumeEvent.volumeType, volumeEvent.volume);
96     auto item = volumeState_.find(volumeEvent.volumeType);
97     if (item != volumeState_.end() && item->second == volumeEvent.volume) {
98         RESSCHED_LOGD("volume not change");
99         return;
100     }
101     nlohmann::json payload;
102     payload["volumeType"] = std::to_string(volumeEvent.volumeType);
103     payload["volumeLevel"] = std::to_string(volumeEvent.volume);
104     volumeState_[volumeEvent.volumeType] = volumeEvent.volume;
105     ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_AUDIO_VOLUME_KEY_CHANGE,
106         volumeEvent.volume, payload);
107 }
108 
OnAudioSceneChange(const AudioStandard::AudioScene audioScene)109 void AudioObserver::OnAudioSceneChange(const AudioStandard::AudioScene audioScene)
110 {
111     RESSCHED_LOGD("enter audioSceneKeyObserver::OnAudioSceneChange, audioScene: %{public}d", audioScene);
112     nlohmann::json payload;
113     payload["audioScene"] = std::to_string(audioScene);
114     ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_AUDIO_SCENE_CHANGE, audioScene, payload);
115 }
116 
OnPreferredOutputDeviceUpdated(const std::vector<std::shared_ptr<AudioStandard::AudioDeviceDescriptor>> & descs)117 void AudioObserver::OnPreferredOutputDeviceUpdated(
118     const std::vector<std::shared_ptr<AudioStandard::AudioDeviceDescriptor>> &descs)
119 {
120     volumeState_.clear();
121     for (const auto &desc : descs) {
122         RESSCHED_LOGI("device change, type: %{public}d", desc->deviceType_);
123         nlohmann::json payload;
124         payload["deviceType"] = std::to_string(desc->deviceType_);
125         payload["deviceId"] = std::to_string(desc->deviceId_);
126         ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_OUTPUT_DEVICE_CHANGE,
127             desc->deviceId_, payload);
128     }
129 }
130 
HandleInnerAudioStateChange(const std::shared_ptr<AudioStandard::AudioRendererChangeInfo> & audioRendererChangeInfo,std::unordered_set<int32_t> & newRunningPid,std::unordered_set<int32_t> & newStopSessionPid)131 void AudioObserver::HandleInnerAudioStateChange(
132     const std::shared_ptr<AudioStandard::AudioRendererChangeInfo> &audioRendererChangeInfo,
133     std::unordered_set<int32_t>& newRunningPid, std::unordered_set<int32_t>& newStopSessionPid)
134 {
135     if (audioRendererChangeInfo == nullptr) {
136         return;
137     }
138     switch (audioRendererChangeInfo->rendererState) {
139         case AudioStandard::RendererState::RENDERER_RUNNING:
140             ProcessRunningSessionState(audioRendererChangeInfo, newRunningPid);
141             break;
142         case AudioStandard::RendererState::RENDERER_STOPPED:
143         case AudioStandard::RendererState::RENDERER_RELEASED:
144         case AudioStandard::RendererState::RENDERER_PAUSED:
145             ProcessStopSessionState(audioRendererChangeInfo, newStopSessionPid);
146             break;
147         default:
148             break;
149     }
150 }
151 
ProcessRunningSessionState(const std::shared_ptr<AudioStandard::AudioRendererChangeInfo> & audioRendererChangeInfo,std::unordered_set<int32_t> & newRunningPid)152 void AudioObserver::ProcessRunningSessionState(
153     const std::shared_ptr<AudioStandard::AudioRendererChangeInfo> &audioRendererChangeInfo,
154     std::unordered_set<int32_t>& newRunningPid)
155 {
156     if (audioRendererChangeInfo == nullptr) {
157         return;
158     }
159     int32_t pid = audioRendererChangeInfo->clientPid;
160     if (processRenderStateMap_.find(pid) != processRenderStateMap_.end()) {
161         processRenderStateMap_[pid].renderRunningSessionSet.emplace(audioRendererChangeInfo->sessionId);
162         return;
163     }
164     ProcessRenderState processRenderState;
165     processRenderState.pid = pid;
166     processRenderState.uid = audioRendererChangeInfo->clientUID;
167     processRenderState.renderRunningSessionSet.emplace(audioRendererChangeInfo->sessionId);
168     processRenderStateMap_[processRenderState.pid] = processRenderState;
169     newRunningPid.emplace(pid);
170 }
171 
ProcessStopSessionState(const std::shared_ptr<AudioStandard::AudioRendererChangeInfo> & audioRendererChangeInfo,std::unordered_set<int32_t> & newStopSessionPid)172 void AudioObserver::ProcessStopSessionState(
173     const std::shared_ptr<AudioStandard::AudioRendererChangeInfo> &audioRendererChangeInfo,
174     std::unordered_set<int32_t>& newStopSessionPid)
175 {
176     if (audioRendererChangeInfo == nullptr) {
177         return;
178     }
179     int32_t pid = audioRendererChangeInfo->clientPid;
180     if (!IsValidPid(pid)) {
181         return;
182     }
183     newStopSessionPid.emplace(pid);
184     if (processRenderStateMap_.find(pid) == processRenderStateMap_.end()) {
185         return;
186     }
187     processRenderStateMap_[pid].renderRunningSessionSet.erase(audioRendererChangeInfo->sessionId);
188 }
189 
HandleStartAudioStateEvent(const std::unordered_set<int32_t> & newRunningPid)190 void AudioObserver::HandleStartAudioStateEvent(const std::unordered_set<int32_t>& newRunningPid)
191 {
192     for (int32_t pid : newRunningPid) {
193         if (processRenderStateMap_.find(pid) == processRenderStateMap_.end() ||
194             processRenderStateMap_[pid].renderRunningSessionSet.size() <= 0) {
195             continue;
196         }
197         nlohmann::json payload;
198         MarshallingInnerAudioRendererChangeInfo(pid, payload);
199         ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_INNER_AUDIO_STATE,
200             ResType::InnerAudioState::AUDIO_STATE_RUNNING, payload);
201     }
202 }
203 
HandleStopAudioStateEvent(const std::unordered_set<int32_t> & newStopSessionPid)204 void AudioObserver::HandleStopAudioStateEvent(const std::unordered_set<int32_t>& newStopSessionPid)
205 {
206     for (int32_t pid : newStopSessionPid) {
207         if (processRenderStateMap_.find(pid) == processRenderStateMap_.end() ||
208             processRenderStateMap_[pid].renderRunningSessionSet.size() > 0) {
209             continue;
210         }
211         nlohmann::json payload;
212         MarshallingInnerAudioRendererChangeInfo(pid, payload);
213         processRenderStateMap_.erase(pid);
214         ResSchedMgr::GetInstance().ReportData(ResType::RES_TYPE_INNER_AUDIO_STATE,
215             ResType::InnerAudioState::AUDIO_STATE_STOP, payload);
216     }
217 }
218 
MarshallingInnerAudioRendererChangeInfo(int32_t pid,nlohmann::json & payload)219 void AudioObserver::MarshallingInnerAudioRendererChangeInfo(int32_t pid, nlohmann::json &payload)
220 {
221     ProcessRenderState processRenderState = processRenderStateMap_[pid];
222     payload["uid"] = std::to_string(processRenderState.uid);
223     payload["pid"] = std::to_string(processRenderState.pid);
224 }
225 
IsValidPid(pid_t pid)226 bool AudioObserver::IsValidPid(pid_t pid)
227 {
228     return (pid >= PID_MIN && pid <= INT32_MAX);
229 }
230 
231 } // namespace ResourceSchedule
232 } // namespace OHOS
233 #endif
234