1 /*
2 * Copyright (c) 2022 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
16 #include "background_audio_controller.h"
17 #include "avsession_log.h"
18 #include "avsession_service.h"
19 #include "avsession_item.h"
20 #include "permission_checker.h"
21
22 namespace OHOS::AVSession {
23 using AudioStandard::RendererState;
24
BackgroundAudioController()25 BackgroundAudioController::BackgroundAudioController() : ptr_(nullptr)
26 {
27 SLOGI("construct");
28 }
29
~BackgroundAudioController()30 BackgroundAudioController::~BackgroundAudioController()
31 {
32 SLOGI("destroy");
33 }
34
Init(AVSessionService * ptr)35 void BackgroundAudioController::Init(AVSessionService *ptr)
36 {
37 ptr_ = ptr;
38 AudioAdapter::GetInstance().AddStreamRendererStateListener([this](const auto& infos) {
39 HandleAudioStreamRendererStateChange(infos);
40 });
41 AppManagerAdapter::GetInstance().SetAppStateChangeObserver([this](int32_t uid, int32_t pid, bool isBackground) {
42 SLOGI("set background observe for uid=%{public}d, pid=%{public}d, isBackground=%{public}d",
43 uid, pid, isBackground);
44 HandleAppMuteState(uid, pid, isBackground);
45 });
46 }
47
OnSessionCreate(const AVSessionDescriptor & descriptor)48 void BackgroundAudioController::OnSessionCreate(const AVSessionDescriptor& descriptor)
49 {
50 std::lock_guard lockGuard(lock_);
51 auto it = sessionUIDs_.find(descriptor.uid_);
52 if (it == sessionUIDs_.end()) {
53 std::set<int32_t> pidSet;
54 pidSet.insert(descriptor.pid_);
55 sessionUIDs_.insert(std::make_pair(descriptor.uid_, pidSet));
56 } else {
57 it->second.insert(descriptor.pid_);
58 }
59 SLOGI("OnSessionCreate remove observe for uid %{public}d pid %{public}d", descriptor.uid_, descriptor.pid_);
60 AppManagerAdapter::GetInstance().RemoveObservedApp(descriptor.uid_);
61 }
62
OnSessionRelease(const AVSessionDescriptor & descriptor)63 void BackgroundAudioController::OnSessionRelease(const AVSessionDescriptor& descriptor)
64 {
65 bool isEmpty = false;
66 {
67 std::lock_guard lockGuard(lock_);
68 auto it = sessionUIDs_.find(descriptor.uid_);
69 if (it != sessionUIDs_.end()) {
70 it->second.erase(descriptor.pid_);
71 if (it->second.empty()) {
72 it = sessionUIDs_.erase(it);
73 isEmpty = true;
74 }
75 }
76 }
77
78 if (descriptor.isThirdPartyApp_ && isEmpty) {
79 SLOGI("OnSessionRelease add observe for uid %{public}d isPidEmpty %{public}d", descriptor.uid_, isEmpty);
80 AppManagerAdapter::GetInstance().AddObservedApp(descriptor.uid_);
81 if (AppManagerAdapter::GetInstance().IsAppBackground(descriptor.uid_, descriptor.pid_)) {
82 auto mute = AudioAdapter::GetInstance().MuteAudioStream(descriptor.uid_, descriptor.pid_);
83 if (mute == AVSESSION_SUCCESS && ptr_ != nullptr) {
84 SLOGI("mute uid=%{public}d done", descriptor.uid_);
85 ptr_->NotifyAudioSessionCheckTrigger(descriptor.uid_);
86 }
87 }
88 }
89 }
90
RendererChangeReport(AudioStandard::AudioRendererChangeInfo & info)91 void BackgroundAudioController::RendererChangeReport(AudioStandard::AudioRendererChangeInfo& info)
92 {
93 if (info.rendererState == AudioStandard::RENDERER_RUNNING ||
94 info.rendererState == AudioStandard::RENDERER_PAUSED ||
95 info.rendererState == AudioStandard::RENDERER_STOPPED) {
96 ptr_->NotifyBackgroundReportCheck(info.clientUID, info.clientPid, info.rendererInfo.streamUsage,
97 info.rendererState);
98 }
99 }
100
101 // LCOV_EXCL_START
HandleAudioStreamRendererStateChange(const AudioRendererChangeInfos & infos)102 void BackgroundAudioController::HandleAudioStreamRendererStateChange(const AudioRendererChangeInfos& infos)
103 {
104 for (const auto& info : infos) {
105 if (info->rendererState != AudioStandard::RENDERER_RUNNING) {
106 continue;
107 }
108 if (!AppManagerAdapter::GetInstance().IsAppBackground(info->clientUID, info->clientPid)) {
109 SLOGI("AudioStreamRendererStateChange add observe for uid %{public}d", info->clientUID);
110 AppManagerAdapter::GetInstance().AddObservedApp(info->clientUID);
111 if (!info->backMute) {
112 SLOGI("uid=%{public}d renderer=%{public}d fore unmute, continue", info->clientUID, info->sessionId);
113 } else {
114 AudioAdapter::GetInstance().UnMuteAudioStream(info->clientUID, info->rendererInfo.streamUsage);
115 }
116 continue;
117 }
118 if (HasAVSession(info->clientUID)) {
119 RendererChangeReport(*info);
120 continue;
121 }
122 if (PermissionChecker::GetInstance().CheckSystemPermissionByUid(info->clientUID)) {
123 SLOGD("uid=%{public}d is system app", info->clientUID);
124 continue;
125 }
126 if (info->backMute) {
127 SLOGI("renderer=%{public}d back is mute, continue", info->sessionId);
128 continue;
129 }
130 auto mute = AudioAdapter::GetInstance().MuteAudioStream(info->clientUID, info->rendererInfo.streamUsage);
131 if (mute == AVSESSION_SUCCESS && ptr_ != nullptr) {
132 SLOGI("mute uid=%{public}d done", info->clientUID);
133 ptr_->NotifyAudioSessionCheckTrigger(info->clientUID);
134 }
135 }
136 }
137
HandleAppMuteState(int32_t uid,int32_t pid,bool isBackground)138 void BackgroundAudioController::HandleAppMuteState(int32_t uid, int32_t pid, bool isBackground)
139 {
140 if (!isBackground) {
141 SLOGI("try unmute uid=%{public}d", uid);
142 AudioAdapter::GetInstance().UnMuteAudioStream(uid);
143 return;
144 }
145 if (PermissionChecker::GetInstance().CheckSystemPermissionByUid(uid)) {
146 SLOGD("uid=%{public}d is system app", uid);
147 return;
148 }
149 if (HasAVSession(uid)) {
150 return;
151 }
152
153 auto mute = AudioAdapter::GetInstance().MuteAudioStream(uid, pid);
154 if (mute == AVSESSION_SUCCESS && ptr_ != nullptr) {
155 SLOGI("mute uid=%{public}d done", uid);
156 ptr_->NotifyAudioSessionCheckTrigger(uid);
157 }
158 }
159 // LCOV_EXCL_STOP
160
IsBackgroundMode(int32_t creatorUid,BackgroundMode backgroundMode) const161 bool BackgroundAudioController::IsBackgroundMode(int32_t creatorUid, BackgroundMode backgroundMode) const
162 {
163 // LCOV_EXCL_START
164 std::vector<std::shared_ptr<ContinuousTaskCallbackInfo>> continuousTaskList;
165 ErrCode code = BackgroundTaskMgr::BackgroundTaskMgrHelper::GetContinuousTaskApps(continuousTaskList);
166 if (code != OHOS::ERR_OK) {
167 SLOGE("uid=%{public}d no continuous task list, code=%{public}d", creatorUid, code);
168 return false;
169 }
170 // LCOV_EXCL_STOP
171
172 for (const auto &task : continuousTaskList) {
173 SLOGD("uid=%{public}d taskCreatorUid=%{public}d", creatorUid, task->GetCreatorUid());
174 if (task->GetCreatorUid() != creatorUid) {
175 continue;
176 }
177
178 std::vector<uint32_t> bgModeIds = task->GetTypeIds();
179 auto it = std::find_if(bgModeIds.begin(), bgModeIds.end(), [ = ](auto mode) {
180 uint32_t uMode = static_cast<uint32_t>(backgroundMode);
181 return (mode == uMode);
182 });
183 if (it != bgModeIds.end()) {
184 SLOGD("uid=%{public}d is audio playback", creatorUid);
185 return true;
186 }
187 }
188 SLOGD("uid=%{public}d isn't audio playback", creatorUid);
189 return false;
190 }
191
HasAVSession(int32_t uid)192 bool BackgroundAudioController::HasAVSession(int32_t uid)
193 {
194 std::lock_guard lockGuard(lock_);
195 bool hasSession = false;
196 auto it = sessionUIDs_.find(uid);
197 if (it != sessionUIDs_.end()) {
198 SLOGD("uid=%{public}d has av_session, no need to handle mute or unmute strategy.", uid);
199 hasSession = true;
200 }
201 return hasSession;
202 }
203 }
204