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 22namespace OHOS::AVSession { 23using AudioStandard::RendererState; 24 25BackgroundAudioController::BackgroundAudioController() : ptr_(nullptr) 26{ 27 SLOGI("construct"); 28} 29 30BackgroundAudioController::~BackgroundAudioController() 31{ 32 SLOGI("destroy"); 33} 34 35void 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 48void BackgroundAudioController::OnSessionCreate(const AVSessionDescriptor& descriptor) 49{ 50 std::lock_guard lockGuard(lock_); 51 sessionUIDs_.insert(descriptor.uid_); 52 SLOGI("OnSessionCreate remove observe for uid %{public}d", descriptor.uid_); 53 AppManagerAdapter::GetInstance().RemoveObservedApp(descriptor.uid_); 54} 55 56void BackgroundAudioController::OnSessionRelease(const AVSessionDescriptor& descriptor) 57{ 58 { 59 std::lock_guard lockGuard(lock_); 60 sessionUIDs_.erase(descriptor.uid_); 61 } 62 63 if (descriptor.isThirdPartyApp_) { 64 SLOGI("OnSessionRelease add observe for uid %{public}d", descriptor.uid_); 65 AppManagerAdapter::GetInstance().AddObservedApp(descriptor.uid_); 66 int32_t uid = descriptor.uid_; 67 bool isRunning = AudioAdapter::GetInstance().GetRendererRunning(uid); 68 if (!isRunning) { 69 SLOGI("renderer state is not running when session release"); 70 return; 71 } 72 if (AppManagerAdapter::GetInstance().IsAppBackground(descriptor.uid_, descriptor.pid_)) { 73 AudioAdapter::GetInstance().MuteAudioStream(descriptor.uid_); 74 if (ptr_ != nullptr) { 75 ptr_->NotifyAudioSessionCheckTrigger(descriptor.uid_); 76 } 77 } 78 } 79} 80 81// LCOV_EXCL_START 82void BackgroundAudioController::HandleAudioStreamRendererStateChange(const AudioRendererChangeInfos& infos) 83{ 84 for (const auto& info : infos) { 85 if (info->rendererState != AudioStandard::RENDERER_RUNNING) { 86 continue; 87 } 88 if (PermissionChecker::GetInstance().CheckSystemPermissionByUid(info->clientUID)) { 89 SLOGD("uid=%{public}d is system app", info->clientUID); 90 continue; 91 } 92 SLOGI("AudioStreamRendererStateChange add observe for uid %{public}d", info->clientUID); 93 AppManagerAdapter::GetInstance().AddObservedApp(info->clientUID); 94 95 if (HasAVSession(info->clientUID)) { 96 continue; 97 } 98 99 if (AppManagerAdapter::GetInstance().IsAppBackground(info->clientUID, info->clientPid)) { 100 AudioAdapter::GetInstance().MuteAudioStream(info->clientUID); 101 if (ptr_ != nullptr) { 102 ptr_->NotifyAudioSessionCheckTrigger(info->clientUID); 103 } 104 } else { 105 AudioAdapter::GetInstance().UnMuteAudioStream(info->clientUID); 106 } 107 } 108} 109 110void BackgroundAudioController::HandleAppMuteState(int32_t uid, int32_t pid, bool isBackground) 111{ 112 if (PermissionChecker::GetInstance().CheckSystemPermissionByUid(uid)) { 113 SLOGD("uid=%{public}d is system app", uid); 114 return; 115 } 116 if (HasAVSession(uid)) { 117 return; 118 } 119 120 if (isBackground) { 121 std::vector<std::shared_ptr<AudioStandard::AudioRendererChangeInfo>> infos; 122 auto ret = AudioStandard::AudioStreamManager::GetInstance()->GetCurrentRendererChangeInfos(infos); 123 if (ret != 0) { 124 SLOGE("get renderer state failed"); 125 return; 126 } 127 bool isRunning = false; 128 for (const auto& info : infos) { 129 if (info->rendererState == AudioStandard::RENDERER_RUNNING && 130 (info->clientUID == uid and info->clientPid == pid)) { 131 isRunning = true; 132 break; 133 } 134 } 135 if (!isRunning) { 136 SLOGI("find uid=%{public}d pid=%{public}d isn't running, return", uid, pid); 137 return; 138 } 139 SLOGI("mute uid=%{public}d", uid); 140 AudioAdapter::GetInstance().MuteAudioStream(uid); 141 if (ptr_ != nullptr) { 142 ptr_->NotifyAudioSessionCheckTrigger(uid); 143 } 144 } else { 145 SLOGI("unmute uid=%{public}d", uid); 146 AudioAdapter::GetInstance().UnMuteAudioStream(uid); 147 } 148} 149// LCOV_EXCL_STOP 150 151bool BackgroundAudioController::IsBackgroundMode(int32_t creatorUid, BackgroundMode backgroundMode) const 152{ 153 // LCOV_EXCL_START 154 std::vector<std::shared_ptr<ContinuousTaskCallbackInfo>> continuousTaskList; 155 ErrCode code = BackgroundTaskMgr::BackgroundTaskMgrHelper::GetContinuousTaskApps(continuousTaskList); 156 if (code != OHOS::ERR_OK) { 157 SLOGE("uid=%{public}d no continuous task list, code=%{public}d", creatorUid, code); 158 return false; 159 } 160 // LCOV_EXCL_STOP 161 162 for (const auto &task : continuousTaskList) { 163 SLOGD("uid=%{public}d taskCreatorUid=%{public}d", creatorUid, task->GetCreatorUid()); 164 if (task->GetCreatorUid() != creatorUid) { 165 continue; 166 } 167 168 std::vector<uint32_t> bgModeIds = task->GetTypeIds(); 169 auto it = std::find_if(bgModeIds.begin(), bgModeIds.end(), [ = ](auto mode) { 170 uint32_t uMode = static_cast<uint32_t>(backgroundMode); 171 return (mode == uMode); 172 }); 173 if (it != bgModeIds.end()) { 174 SLOGD("uid=%{public}d is audio playback", creatorUid); 175 return true; 176 } 177 } 178 SLOGD("uid=%{public}d isn't audio playback", creatorUid); 179 return false; 180} 181 182bool BackgroundAudioController::HasAVSession(int32_t uid) 183{ 184 std::lock_guard lockGuard(lock_); 185 bool hasSession = false; 186 auto it = sessionUIDs_.find(uid); 187 if (it != sessionUIDs_.end()) { 188 SLOGD("uid=%{public}d has av_session, no need to handle mute or unmute strategy.", uid); 189 hasSession = true; 190 } 191 return hasSession; 192} 193} 194