* Copyright (c) 2023-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LOG_TAG
#define LOG_TAG "AudioService"
#endif
#include "audio_service.h"
#include "audio_stream_common.h"
#include <unistd.h>
#include <algorithm>
#include <thread>
#include "ipc_skeleton.h"
#include "audio_errors.h"
#include "audio_common_log.h"
#include "audio_utils.h"
#include "i_hpae_manager.h"
#include "policy_handler.h"
#include "core_service_handler.h"
#include "ipc_stream_in_server.h"
#include "stream_dfx_manager.h"
#include "common/hdi_adapter_info.h"
#include "manager/hdi_adapter_manager.h"
#include "source/i_audio_capture_source.h"
#include "audio_volume.h"
#include "audio_performance_monitor.h"
#include "privacy_kit.h"
#include "media_monitor_manager.h"
#ifdef HAS_FEATURE_INNERCAPTURER
#include "playback_capturer_manager.h"
#endif
#include "audio_resource_service.h"
#include "stream_dfx_manager.h"
#include "audio_privacy_manager_in_server.h"
namespace OHOS {
namespace AudioStandard {
static const uint32_t UPDATE_MUTE_CONTROL_SET_TIME_OUT = 15;
static const uint32_t BLOCK_HIBERNATE_CALLBACK_IN_MS = 5000;
static const uint32_t RECHECK_SINK_STATE_IN_US = 300000;
static const int32_t MEDIA_SERVICE_UID = 1013;
static const int32_t INVALID_APP_UID = -1;
static const int32_t INVALID_APP_CREATED_AUDIO_STREAM_NUM = 0;
static const int32_t UID_AUDIO = 1041;
namespace {
static inline const std::unordered_set<SourceType> specialSourceTypeSet_ = {
SOURCE_TYPE_PLAYBACK_CAPTURE,
SOURCE_TYPE_WAKEUP,
SOURCE_TYPE_VIRTUAL_CAPTURE,
SOURCE_TYPE_REMOTE_CAST
};
static inline const std::unordered_set<AudioStreamType> workgroupSupportStreamTypeSet_ {
STREAM_MUSIC,
STREAM_MOVIE,
STREAM_SPEECH,
STREAM_NAVIGATION,
STREAM_VOICE_COMMUNICATION,
};
const size_t MAX_FG_LIST_SIZE = 10;
}
AudioService *AudioService::GetInstance()
{
static AudioService AudioService;
return &AudioService;
}
AudioService::AudioService()
{
AUDIO_INFO_LOG("AudioService()");
}
AudioService::~AudioService()
{
AUDIO_INFO_LOG("~AudioService()");
}
#ifdef SUPPORT_LOW_LATENCY
void AudioService::SetEndpointMuteForSwitchDevice(const std::string &deviceClass, bool mute)
{
AUDIO_INFO_LOG("SetEndpointMuteForSwitchDevice deviceClass:%{public}s mute:%{public}d",
deviceClass.c_str(), mute);
HPAE::IHpaeManager::GetHpaeManager().SetSinkMuteForSwitchDevice(deviceClass, mute);
}
#endif
void AudioService::DisableLoopback()
{
HdiAdapterManager &manager = HdiAdapterManager::GetInstance();
std::shared_ptr<IDeviceManager> deviceManager = manager.GetDeviceManager(HDI_DEVICE_MANAGER_TYPE_LOCAL);
CHECK_AND_RETURN_LOG(deviceManager != nullptr, "local device manager is nullptr");
deviceManager->SetAudioParameter("primary", AudioParamKey::NONE, "", "Karaoke_enable=disable");
}
sptr<IpcStreamInServer> AudioService::GetIpcStream(const AudioProcessConfig &config, int32_t &ret)
{
Trace trace("AudioService::GetIpcStream");
#ifdef HAS_FEATURE_INNERCAPTURER
if (!isRegisterCapturerFilterListened_) {
AUDIO_INFO_LOG("isRegisterCapturerFilterListened_ is false");
PlaybackCapturerManager::GetInstance()->RegisterCapturerFilterListener(this);
isRegisterCapturerFilterListened_ = true;
}
#endif
sptr<IpcStreamInServer> ipcStreamInServer = IpcStreamInServer::Create(config, ret);
if (ipcStreamInServer == nullptr && config.audioMode == AUDIO_MODE_PLAYBACK) {
StreamDfxManager::GetInstance().SendAudioErrorEvent(static_cast<int32_t>(config.appInfo.appUid),
PLAY_CREATE_OPERATION_FAILED, "IpcStreamInServer create failed", false);
AUDIO_ERR_LOG("IpcStreamInServer::Create failed, ret: %{public}d", ret);
}
if (ipcStreamInServer != nullptr && config.audioMode == AUDIO_MODE_PLAYBACK) {
uint32_t sessionId = 0;
std::shared_ptr<RendererInServer> renderer = ipcStreamInServer->GetRenderer();
if (renderer != nullptr && renderer->GetSessionId(sessionId) == SUCCESS) {
InsertRenderer(sessionId, renderer);
#ifdef HAS_FEATURE_INNERCAPTURER
CheckInnerCapForRenderer(sessionId, renderer);
#endif
CheckRenderSessionMuteState(sessionId, renderer);
CoreServiceHandler::GetInstance().UpdateSessionOperation(sessionId, SESSION_OPERATION_CREATE);
}
}
if (ipcStreamInServer != nullptr && config.audioMode == AUDIO_MODE_RECORD) {
uint32_t sessionId = 0;
std::shared_ptr<CapturerInServer> capturer = ipcStreamInServer->GetCapturer();
if (capturer != nullptr && capturer->GetSessionId(sessionId) == SUCCESS) {
InsertCapturer(sessionId, capturer);
CheckCaptureSessionMuteState(sessionId, capturer);
CoreServiceHandler::GetInstance().UpdateSessionOperation(sessionId, SESSION_OPERATION_CREATE);
}
}
return ipcStreamInServer;
}
void AudioService::UpdateMuteControlSet(uint32_t sessionId, bool muteFlag)
{
int32_t xCollieFlag = (1 | 2);
AudioXCollie audioXCollie("AudioService::UpdateMuteControlSet", UPDATE_MUTE_CONTROL_SET_TIME_OUT,
nullptr, nullptr, xCollieFlag);
if (sessionId < MIN_STREAMID || sessionId > MAX_STREAMID) {
AUDIO_WARNING_LOG("Invalid sessionid %{public}u", sessionId);
return;
}
std::lock_guard<std::mutex> lock(mutedSessionsMutex_);
if (muteFlag) {
mutedSessions_.insert(sessionId);
return;
}
if (mutedSessions_.find(sessionId) != mutedSessions_.end()) {
mutedSessions_.erase(sessionId);
} else {
AUDIO_WARNING_LOG("Session id %{public}u not in the set", sessionId);
}
}
void AudioService::RemoveIdFromMuteControlSet(uint32_t sessionId)
{
std::lock_guard<std::mutex> mutedSessionsLock(mutedSessionsMutex_);
if (mutedSessions_.find(sessionId) != mutedSessions_.end()) {
mutedSessions_.erase(sessionId);
} else {
AUDIO_WARNING_LOG("Session id %{public}u not in the set", sessionId);
}
}
void AudioService::CheckRenderSessionMuteState(uint32_t sessionId, std::shared_ptr<RendererInServer> renderer)
{
std::unique_lock<std::mutex> mutedSessionsLock(mutedSessionsMutex_);
if (mutedSessions_.find(sessionId) != mutedSessions_.end() || IsMuteSwitchStream(sessionId)) {
mutedSessionsLock.unlock();
AUDIO_INFO_LOG("Session %{public}u is in control", sessionId);
renderer->SetNonInterruptMute(true);
}
}
void AudioService::CheckCaptureSessionMuteState(uint32_t sessionId, std::shared_ptr<CapturerInServer> capturer)
{
std::unique_lock<std::mutex> mutedSessionsLock(mutedSessionsMutex_);
if (mutedSessions_.find(sessionId) != mutedSessions_.end() || IsMuteSwitchStream(sessionId)) {
mutedSessionsLock.unlock();
AUDIO_INFO_LOG("Session %{public}u is in control", sessionId);
capturer->SetNonInterruptMute(true);
}
}
bool AudioService::IsMuteSwitchStream(uint32_t sessionId)
{
std::lock_guard<std::mutex> muteSwitchStreamLock(muteSwitchStreamSetMutex_);
if (muteSwitchStreams_.count(sessionId)) {
AUDIO_INFO_LOG("find session %{public}u in muteSwitchStreams_", sessionId);
muteSwitchStreams_.erase(sessionId);
return true;
}
return false;
}
void AudioService::InsertRenderer(uint32_t sessionId, std::shared_ptr<RendererInServer> renderer)
{
std::unique_lock<std::mutex> lock(rendererMapMutex_);
AUDIO_INFO_LOG("Insert renderer:%{public}u into map", sessionId);
allRendererMap_[sessionId] = renderer;
}
void AudioService::SaveForegroundList(std::vector<std::string> list)
{
std::lock_guard<std::mutex> lock(foregroundSetMutex_);
if (list.size() > MAX_FG_LIST_SIZE) {
AUDIO_ERR_LOG("invalid list size %{public}zu", list.size());
return;
}
foregroundSet_.clear();
foregroundUidSet_.clear();
for (auto &item : list) {
AUDIO_WARNING_LOG("Add for hap: %{public}s", item.c_str());
foregroundSet_.insert(item);
}
}
bool AudioService::MatchForegroundList(const std::string &bundleName, uint32_t uid)
{
std::lock_guard<std::mutex> lock(foregroundSetMutex_);
if (foregroundSet_.find(bundleName) != foregroundSet_.end()) {
AUDIO_WARNING_LOG("find hap %{public}s in list!", bundleName.c_str());
if (uid != 0) {
foregroundUidSet_.insert(uid);
}
return true;
}
return false;
}
bool AudioService::InForegroundList(uint32_t uid)
{
std::lock_guard<std::mutex> lock(foregroundSetMutex_);
if (foregroundUidSet_.find(uid) != foregroundUidSet_.end()) {
AUDIO_INFO_LOG("find hap %{public}d in list!", uid);
return true;
}
return false;
}
void AudioService::SaveRenderWhitelist(std::vector<std::string> list)
{
std::lock_guard<std::mutex> lock(renderWhitelistMutex_);
renderWhitelist_.clear();
for (auto &item : list) {
AUDIO_INFO_LOG("Add for hap: %{public}s", item.c_str());
renderWhitelist_.insert(item);
}
}
bool AudioService::InRenderWhitelist(const std::string bundleName)
{
std::lock_guard<std::mutex> lock(renderWhitelistMutex_);
CHECK_AND_RETURN_RET_LOG(renderWhitelist_.find(bundleName) != renderWhitelist_.end(),
false, "hap %{public}s not in list", bundleName.c_str());
AUDIO_INFO_LOG("find hap %{public}s in list!", bundleName.c_str());
return true;
}
bool AudioService::UpdateForegroundState(uint32_t appTokenId, bool isActive)
{
std::string str = "UpdateForegroundState " + std::to_string(appTokenId) + (isActive ? "to active" : "to deactive");
Trace trace(str);
WatchTimeout guard(str);
int32_t res = OHOS::Security::AccessToken::PrivacyKit::SetHapWithFGReminder(appTokenId, isActive);
AUDIO_INFO_LOG("res is %{public}d for %{public}s", res, str.c_str());
return res;
}
void AudioService::DumpForegroundList(std::string &dumpString)
{
std::lock_guard<std::mutex> lock(foregroundSetMutex_);
std::stringstream temp;
temp << "DumpForegroundList:\n";
int32_t index = 0;
for (auto item : foregroundSet_) {
temp << " " << std::to_string(index++) << ": " << item << "\n";
}
dumpString = temp.str();
}
int32_t AudioService::GetStandbyStatus(uint32_t sessionId, bool &isStandby, int64_t &enterStandbyTime)
{
std::unique_lock<std::mutex> lockRender(rendererMapMutex_);
if (allRendererMap_.count(sessionId)) {
std::shared_ptr<RendererInServer> render = allRendererMap_[sessionId].lock();
if (render == nullptr) {
return ERR_INVALID_PARAM;
}
return render->GetStandbyStatus(isStandby, enterStandbyTime);
}
lockRender.unlock();
return ERR_INVALID_PARAM;
}
void AudioService::RemoveRenderer(uint32_t sessionId, bool isSwitchStream)
{
std::unique_lock<std::mutex> lock(rendererMapMutex_);
AUDIO_INFO_LOG("Renderer:%{public}u will be removed.", sessionId);
if (!allRendererMap_.count(sessionId)) {
AUDIO_WARNING_LOG("Renderer in not in map!");
return;
}
allRendererMap_.erase(sessionId);
if (!isSwitchStream) {
RemoveIdFromMuteControlSet(sessionId);
}
AudioPerformanceMonitor::GetInstance().DeleteSilenceMonitor(sessionId);
}
void AudioService::InsertCapturer(uint32_t sessionId, std::shared_ptr<CapturerInServer> capturer)
{
std::unique_lock<std::mutex> lock(capturerMapMutex_);
AUDIO_INFO_LOG("Insert capturer:%{public}u into map", sessionId);
allCapturerMap_[sessionId] = capturer;
}
void AudioService::RemoveCapturer(uint32_t sessionId, bool isSwitchStream)
{
std::unique_lock<std::mutex> lock(capturerMapMutex_);
AUDIO_INFO_LOG("Capturer: %{public}u will be removed.", sessionId);
if (!allCapturerMap_.count(sessionId)) {
StreamDfxManager::GetInstance().SendAudioErrorEvent(static_cast<int32_t>(getuid()),
RECORD_QUERY_ILLEGAL_STATE, "Capturer in not in map", false);
AUDIO_WARNING_LOG("Capturer in not in map!");
return;
}
allCapturerMap_.erase(sessionId);
{
std::unique_lock<std::mutex> muteStatelock(muteStateMapMutex_);
muteStateCallbacks_.erase(sessionId);
}
if (!isSwitchStream) {
RemoveIdFromMuteControlSet(sessionId);
}
}
void AudioService::AddFilteredRender(int32_t innerCapId, std::shared_ptr<RendererInServer> renderer)
{
if (!filteredRendererMap_.count(innerCapId)) {
std::vector<std::weak_ptr<RendererInServer>> renders;
filteredRendererMap_[innerCapId] = renders;
}
filteredRendererMap_[innerCapId].push_back(renderer);
}
#ifdef HAS_FEATURE_INNERCAPTURER
void AudioService::CheckInnerCapForRenderer(uint32_t sessionId, std::shared_ptr<RendererInServer> renderer)
{
CHECK_AND_RETURN_LOG(renderer != nullptr, "renderer is null.");
std::unique_lock<std::mutex> lock(rendererMapMutex_);
{
std::lock_guard<std::mutex> lock(workingConfigsMutex_);
if (workingConfigs_.size() == 0) {
return;
}
}
std::set<int32_t> captureIds;
if (ShouldBeInnerCap(renderer->processConfig_, captureIds)) {
for (auto innerCapId : captureIds) {
AddFilteredRender(innerCapId, renderer);
renderer->EnableInnerCap(innerCapId);
}
}
}
InnerCapFilterPolicy AudioService::GetInnerCapFilterPolicy(int32_t innerCapId)
{
if (!workingConfigs_.count(innerCapId)) {
AUDIO_ERR_LOG("error, invalid innerCapId");
return POLICY_INVALID;
}
auto usagesSize = workingConfigs_[innerCapId].filterOptions.usages.size();
auto pidsSize = workingConfigs_[innerCapId].filterOptions.pids.size();
if (usagesSize == 0 && pidsSize == 0) {
AUDIO_ERR_LOG("error, invalid usages and pids");
return POLICY_INVALID;
}
if (usagesSize > 0 && pidsSize == 0) {
AUDIO_INFO_LOG("usages only");
return POLICY_USAGES_ONLY;
}
return POLICY_USAGES_AND_PIDS;
}
template<typename T>
bool isFilterMatched(const std::vector<T> ¶ms, T param, FilterMode mode)
{
bool isFound = std::count(params.begin(), params.end(), param) != 0;
return (mode == FilterMode::INCLUDE && isFound) || (mode == FilterMode::EXCLUDE && !isFound);
}
bool AudioService::CanCapturePrivateStream(const AudioPlaybackCaptureConfig &config) const
{
return config.filterOptions.capturePrivatePrivacyStreams;
}
bool AudioService::ShouldBeInnerCap(const AudioProcessConfig &rendererConfig, int32_t innerCapId)
{
std::lock_guard<std::mutex> lock(workingConfigsMutex_);
if (innerCapId == 0 || !workingConfigs_.count(innerCapId)) {
return false;
}
const auto &config = workingConfigs_[innerCapId];
bool canBeCaptured = rendererConfig.privacyType == AudioPrivacyType::PRIVACY_TYPE_PUBLIC ||
(rendererConfig.privacyType == AudioPrivacyType::PRIVACY_TYPE_PRIVATE && CanCapturePrivateStream(config));
if (!canBeCaptured) {
AUDIO_INFO_LOG("%{public}d privacyType %{public}d can not be captured by innerCapId %{public}d",
rendererConfig.appInfo.appPid, rendererConfig.privacyType, innerCapId);
return false;
}
return CheckShouldCap(rendererConfig, innerCapId);
}
bool AudioService::ShouldBeInnerCap(const AudioProcessConfig &rendererConfig, std::set<int32_t> &beCapIds)
{
bool ret = false;
std::lock_guard<std::mutex> lock(workingConfigsMutex_);
for (auto& filter : workingConfigs_) {
bool canBeCaptured = rendererConfig.privacyType == AudioPrivacyType::PRIVACY_TYPE_PUBLIC ||
(rendererConfig.privacyType == AudioPrivacyType::PRIVACY_TYPE_PRIVATE &&
CanCapturePrivateStream(filter.second));
if (!canBeCaptured) {
continue;
}
if (CheckShouldCap(rendererConfig, filter.first)) {
ret = true;
beCapIds.insert(filter.first);
}
}
return ret;
}
bool AudioService::CheckShouldCap(const AudioProcessConfig &rendererConfig, int32_t innerCapId)
{
InnerCapFilterPolicy filterPolicy = GetInnerCapFilterPolicy(innerCapId);
if (workingConfigs_[innerCapId].filterOptions.playbackCaptureUid != PLAYBACKCAPTURER_RECORD_ALL) {
CHECK_AND_RETURN_RET_LOG(
(workingConfigs_[innerCapId].filterOptions.playbackCaptureUid == rendererConfig.appInfo.appUid),
false, "only %{public}d need be recorded, current %{public}d is invalid",
workingConfigs_[innerCapId].filterOptions.playbackCaptureUid, rendererConfig.appInfo.appUid);
}
bool res = false;
switch (filterPolicy) {
case POLICY_INVALID:
return false;
case POLICY_USAGES_ONLY:
res = isFilterMatched(workingConfigs_[innerCapId].filterOptions.usages,
rendererConfig.rendererInfo.streamUsage, workingConfigs_[innerCapId].filterOptions.usageFilterMode);
break;
case POLICY_USAGES_AND_PIDS:
res = isFilterMatched(workingConfigs_[innerCapId].filterOptions.usages,
rendererConfig.rendererInfo.streamUsage,
workingConfigs_[innerCapId].filterOptions.usageFilterMode) &&
isFilterMatched(workingConfigs_[innerCapId].filterOptions.pids, rendererConfig.appInfo.appPid,
workingConfigs_[innerCapId].filterOptions.pidFilterMode);
break;
default:
break;
}
AUDIO_INFO_LOG("pid:%{public}d usage:%{public}d result:%{public}s capId:%{public}d",
rendererConfig.appInfo.appPid, rendererConfig.rendererInfo.streamUsage, res ? "true" : "false", innerCapId);
return res;
}
#endif
bool AudioService::ShouldBeDualTone(const AudioProcessConfig &config, const std::string &dupSinkName)
{
if (dupSinkName != "Speaker") {
return true;
}
CHECK_AND_RETURN_RET_LOG(Util::IsRingerOrAlarmerStreamUsage(config.rendererInfo.streamUsage), false,
"Wrong usage ,should not be dualtone");
AudioDeviceDescriptor deviceInfo(AudioDeviceDescriptor::DEVICE_INFO);
bool ret = PolicyHandler::GetInstance().GetProcessDeviceInfo(config, false, deviceInfo);
if (!ret) {
AUDIO_WARNING_LOG("GetProcessDeviceInfo from audio policy server failed!");
return false;
}
if (config.audioMode != AUDIO_MODE_PLAYBACK) {
AUDIO_WARNING_LOG("No playback mode!");
return false;
}
AUDIO_INFO_LOG("Get DeviceInfo from policy server success, deviceType: %{public}d, "
"supportLowLatency: %{public}d", deviceInfo.deviceType_, deviceInfo.isLowLatencyDevice_);
if (deviceInfo.deviceType_ == DEVICE_TYPE_WIRED_HEADSET || deviceInfo.deviceType_ == DEVICE_TYPE_WIRED_HEADPHONES ||
deviceInfo.deviceType_ == DEVICE_TYPE_BLUETOOTH_A2DP || deviceInfo.deviceType_ == DEVICE_TYPE_USB_HEADSET ||
deviceInfo.deviceType_ == DEVICE_TYPE_USB_ARM_HEADSET || deviceInfo.deviceType_ == DEVICE_TYPE_REMOTE_CAST ||
(deviceInfo.deviceType_ == DEVICE_TYPE_SPEAKER && deviceInfo.networkId_ != std::string(LOCAL_NETWORK_ID)) ||
deviceInfo.deviceType_ == DEVICE_TYPE_HEARING_AID) {
switch (config.rendererInfo.streamUsage) {
case STREAM_USAGE_ALARM:
case STREAM_USAGE_VOICE_RINGTONE:
case STREAM_USAGE_RINGTONE:
AUDIO_WARNING_LOG("Should DualTone.");
return true;
default:
return false;
}
}
return false;
}
#ifdef HAS_FEATURE_INNERCAPTURER
int32_t AudioService::OnInitInnerCapList(int32_t innerCapId)
{
AUDIO_INFO_LOG("workingInnerCapId_ is %{public}d", innerCapId);
std::vector<std::shared_ptr<RendererInServer>> renderers;
{
std::unique_lock<std::mutex> lock(rendererMapMutex_);
for (auto it = allRendererMap_.begin(); it != allRendererMap_.end(); it++) {
std::shared_ptr<RendererInServer> renderer = it->second.lock();
if (renderer == nullptr) {
AUDIO_WARNING_LOG("Renderer is already released!");
continue;
}
if (ShouldBeInnerCap(renderer->processConfig_, innerCapId)) {
renderer->EnableInnerCap(innerCapId);
AddFilteredRender(innerCapId, renderer);
}
renderers.push_back(std::move(renderer));
}
}
return SUCCESS;
}
int32_t AudioService::OnUpdateInnerCapList(int32_t innerCapId)
{
AUDIO_INFO_LOG("workingInnerCapId_ is %{public}d", innerCapId);
std::unique_lock<std::mutex> lock(rendererMapMutex_);
if (filteredRendererMap_.count(innerCapId)) {
for (size_t i = 0; i < filteredRendererMap_[innerCapId].size(); i++) {
std::shared_ptr<RendererInServer> renderer = filteredRendererMap_[innerCapId][i].lock();
if (renderer == nullptr) {
AUDIO_WARNING_LOG("Renderer is already released!");
continue;
}
if (!ShouldBeInnerCap(renderer->processConfig_, innerCapId)) {
renderer->DisableInnerCap(innerCapId);
}
}
filteredRendererMap_.erase(innerCapId);
}
lock.unlock();
return OnInitInnerCapList(innerCapId);
}
#endif
int32_t AudioService::EnableDualStreamForNormalStream(const uint32_t sessionId, const std::string &dupSinkName)
{
AUDIO_INFO_LOG("sessionId is %{public}d", sessionId);
std::lock_guard<std::mutex> lock(rendererMapMutex_);
CHECK_AND_CALL_FUNC_RETURN_RET_LOG(allRendererMap_.count(sessionId) > 0, ERR_OPERATION_FAILED,
StreamDfxManager::GetInstance().SendAudioErrorEvent(INVALID_APP_UID,
PLAY_CREATE_INVALID_INDEX, "EnableDualStreamForNormalStream sessionId not in map", false),
"sessionId %{public}u not in map", sessionId);
auto weakRenderer = allRendererMap_[sessionId];
auto renderer = weakRenderer.lock();
CHECK_AND_CALL_FUNC_RETURN_RET_LOG(renderer != nullptr, ERR_OPERATION_FAILED,
StreamDfxManager::GetInstance().SendAudioErrorEvent(INVALID_APP_UID,
PLAY_CREATE_NULL_POINTER, "EnableDualStreamForNormalStream renderer is null", false),
"renderer is null");
CHECK_AND_RETURN_RET(ShouldBeDualTone(renderer->processConfig_, dupSinkName), SUCCESS);
renderer->EnableDualTone(dupSinkName);
return SUCCESS;
}
int32_t AudioService::DisableDualStreamForNormalStream(const uint32_t sessionId)
{
AUDIO_INFO_LOG("disable dual tone, sessionId is %{public}d", sessionId);
std::lock_guard<std::mutex> lock(rendererMapMutex_);
CHECK_AND_CALL_FUNC_RETURN_RET_LOG(allRendererMap_.count(sessionId) > 0, ERR_OPERATION_FAILED,
StreamDfxManager::GetInstance().SendAudioErrorEvent(INVALID_APP_UID,
PLAY_CREATE_INVALID_INDEX, "DisableDualStreamForNormalStream sessionId not in map", false),
"sessionId %{public}u not in map", sessionId);
auto weakRenderer = allRendererMap_[sessionId];
auto renderer = weakRenderer.lock();
CHECK_AND_CALL_FUNC_RETURN_RET_LOG(renderer != nullptr, ERR_OPERATION_FAILED,
StreamDfxManager::GetInstance().SendAudioErrorEvent(INVALID_APP_UID,
PLAY_CREATE_NULL_POINTER, "DisableDualStreamForNormalStream renderer is null", false),
"renderer is null");
renderer->DisableDualTone();
return SUCCESS;
}
int32_t AudioService::OnCapturerFilterChange(uint32_t sessionId, const AudioPlaybackCaptureConfig &newConfig,
int32_t innerCapId)
{
#ifdef HAS_FEATURE_INNERCAPTURER
Trace trace("AudioService::OnCapturerFilterChange");
bool isOldCap = false;
{
std::lock_guard<std::mutex> lock(workingConfigsMutex_);
if (workingConfigs_.count(innerCapId)) {
workingConfigs_[innerCapId] = newConfig;
isOldCap = true;
} else {
workingConfigs_[innerCapId] = newConfig;
}
}
if (isOldCap) {
return OnUpdateInnerCapList(innerCapId);
} else {
return OnInitInnerCapList(innerCapId);
}
AUDIO_WARNING_LOG("%{public}u is working, comming %{public}u will not work!", innerCapId, sessionId);
return ERR_OPERATION_FAILED;
#endif
return SUCCESS;
}
int32_t AudioService::OnCapturerFilterRemove(uint32_t sessionId, int32_t innerCapId)
{
#ifdef HAS_FEATURE_INNERCAPTURER
{
std::lock_guard<std::mutex> lock(workingConfigsMutex_);
if (!workingConfigs_.count(innerCapId)) {
AUDIO_WARNING_LOG("%{public}u is working, remove %{public}u will not work!", innerCapId, sessionId);
return SUCCESS;
}
workingConfigs_.erase(innerCapId);
}
std::vector<std::shared_ptr<RendererInServer>> renderers;
{
std::lock_guard<std::mutex> lock(rendererMapMutex_);
if (filteredRendererMap_.count(innerCapId)) {
for (size_t i = 0; i < filteredRendererMap_[innerCapId].size(); i++) {
std::shared_ptr<RendererInServer> renderer = filteredRendererMap_[innerCapId][i].lock();
if (renderer == nullptr) {
AUDIO_WARNING_LOG("Find renderer is already released!");
continue;
}
renderer->DisableInnerCap(innerCapId);
renderers.push_back(std::move(renderer));
}
AUDIO_INFO_LOG("Filter removed, clear %{public}zu filtered renderer.",
filteredRendererMap_[innerCapId].size());
filteredRendererMap_.erase(innerCapId);
}
}
#endif
return SUCCESS;
}
bool AudioService::IsEndpointTypeVoip(const AudioProcessConfig &config, AudioDeviceDescriptor &deviceInfo)
{
if (config.rendererInfo.streamUsage == STREAM_USAGE_VOICE_COMMUNICATION ||
config.rendererInfo.streamUsage == STREAM_USAGE_VIDEO_COMMUNICATION) {
return config.rendererInfo.originalFlag == AUDIO_FLAG_VOIP_FAST || deviceInfo.networkId_ != LOCAL_NETWORK_ID;
}
if (config.capturerInfo.sourceType == SOURCE_TYPE_VOICE_COMMUNICATION) {
return config.capturerInfo.originalFlag == AUDIO_FLAG_VOIP_FAST || deviceInfo.networkId_ != LOCAL_NETWORK_ID;
}
return false;
}
bool AudioService::GetRemoteDeviceName(const std::string &deviceId, std::string &deviceName)
{
return PolicyHandler::GetInstance().GetRemoteDeviceName(deviceId, deviceName);
}
#ifdef SUPPORT_LOW_LATENCY
AudioDeviceDescriptor AudioService::GetDeviceInfoForProcess(const AudioProcessConfig &config,
AudioStreamInfo &streamInfo, bool &isUltraFast, bool isReloadProcess)
{
AudioDeviceDescriptor deviceInfo(AudioDeviceDescriptor::DEVICE_INFO);
int32_t ret = CoreServiceHandler::GetInstance().GetProcessDeviceInfoBySessionId(config.originalSessionId,
deviceInfo, streamInfo, isUltraFast, isReloadProcess);
if (ret == SUCCESS) {
AUDIO_INFO_LOG("Get DeviceInfo from policy: deviceType:%{public}d, supportLowLatency:%{public}s"
" a2dpOffloadFlag:%{public}d", deviceInfo.deviceType_, (deviceInfo.isLowLatencyDevice_ ? "true" : "false"),
deviceInfo.a2dpOffloadFlag_);
if (AudioStreamCommon::IsVoipMmap(config.rendererInfo.streamUsage, config.capturerInfo.sourceType)) {
if (config.streamInfo.samplingRate <= SAMPLE_RATE_16000) {
AUDIO_INFO_LOG("VoIP 16K");
streamInfo = {SAMPLE_RATE_16000, ENCODING_PCM, SAMPLE_S16LE, STEREO, CH_LAYOUT_STEREO};
} else {
AUDIO_INFO_LOG("VoIP 48K");
streamInfo = {SAMPLE_RATE_48000, ENCODING_PCM, SAMPLE_S16LE, STEREO, CH_LAYOUT_STEREO};
}
} else {
AUDIO_INFO_LOG("Fast stream use rate:%{public}d format:%{public}d", streamInfo.samplingRate,
streamInfo.format);
deviceInfo.deviceName_ = "mmap_device";
}
return deviceInfo;
}
AUDIO_WARNING_LOG("GetProcessDeviceInfo from audio policy server failed!");
if (config.audioMode == AUDIO_MODE_RECORD) {
deviceInfo.deviceId_ = 1;
deviceInfo.networkId_ = LOCAL_NETWORK_ID;
deviceInfo.deviceRole_ = INPUT_DEVICE;
deviceInfo.deviceType_ = DEVICE_TYPE_MIC;
} else {
deviceInfo.deviceId_ = 6;
deviceInfo.networkId_ = LOCAL_NETWORK_ID;
deviceInfo.deviceRole_ = OUTPUT_DEVICE;
deviceInfo.deviceType_ = DEVICE_TYPE_SPEAKER;
}
streamInfo = {SAMPLE_RATE_48000, ENCODING_PCM, SAMPLE_S16LE, STEREO,
CH_LAYOUT_STEREO};
deviceInfo.deviceName_ = "mmap_device";
return deviceInfo;
}
#endif
int32_t AudioService::NotifyStreamVolumeChanged(AudioStreamType streamType, float volume)
{
std::lock_guard<std::mutex> lock(processListMutex_);
int32_t ret = SUCCESS;
UpdateSystemVolumeForWorkgroup(streamType, volume);
return ret;
}
void AudioService::Dump(std::string &dumpString)
{
AUDIO_INFO_LOG("AudioService dump begin");
{
std::lock_guard<std::mutex> lock(workingConfigsMutex_);
for (auto &workingConfig_ : workingConfigs_) {
AppendFormat(dumpString, "InnerCapid: %s - InnerCap filter: %s\n",
std::to_string(workingConfig_.first).c_str(),
ProcessConfig::DumpInnerCapConfig(workingConfig_.second).c_str());
}
}
{
std::lock_guard<std::mutex> lock(rendererMapMutex_);
for (const auto &item : allRendererMap_) {
std::shared_ptr<RendererInServer> renderer = item.second.lock();
if (renderer) {
renderer->Dump(dumpString);
}
}
}
{
std::lock_guard<std::mutex> lock(streamLifeCycleMutex_);
AppendFormat(dumpString, " - currentRendererStreamCnt is %d\n", currentRendererStreamCnt_);
for (auto it : appUseNumMap_) {
AppendFormat(dumpString, " - appUseNumMap_ appUid: %d\n", it.first);
AppendFormat(dumpString, " - appUseNumMap_ appUid created stream: %d\n", it.second);
}
}
PolicyHandler::GetInstance().Dump(dumpString);
AudioVolume::GetInstance()->Dump(dumpString);
}
float AudioService::GetMaxAmplitude(bool isOutputDevice)
{
return 0;
}
std::shared_ptr<RendererInServer> AudioService::GetRendererBySessionID(const uint32_t &sessionID)
{
std::lock_guard<std::mutex> lock(rendererMapMutex_);
if (allRendererMap_.count(sessionID)) {
return allRendererMap_[sessionID].lock();
} else {
return nullptr;
}
}
std::shared_ptr<CapturerInServer> AudioService::GetCapturerBySessionID(const uint32_t &sessionID)
{
std::lock_guard<std::mutex> lock(rendererMapMutex_);
if (allCapturerMap_.count(sessionID)) {
return allCapturerMap_[sessionID].lock();
} else {
return std::shared_ptr<CapturerInServer>();
}
}
void AudioService::SetNonInterruptMute(const uint32_t sessionId, const bool muteFlag)
{
AUDIO_INFO_LOG("SessionId: %{public}u, muteFlag: %{public}d", sessionId, muteFlag);
std::unique_lock<std::mutex> rendererLock(rendererMapMutex_);
if (allRendererMap_.count(sessionId)) {
std::shared_ptr<RendererInServer> renderer = allRendererMap_[sessionId].lock();
if (renderer == nullptr) {
AUDIO_ERR_LOG("rendererinserver is null");
rendererLock.unlock();
return;
}
renderer->SetNonInterruptMute(muteFlag);
AUDIO_INFO_LOG("allRendererMap_ has sessionId");
UpdateSessionMuteStatus(sessionId, muteFlag);
rendererLock.unlock();
return;
}
rendererLock.unlock();
std::unique_lock<std::mutex> capturerLock(capturerMapMutex_);
if (allCapturerMap_.count(sessionId)) {
std::shared_ptr<CapturerInServer> capturer = allCapturerMap_[sessionId].lock();
if (capturer == nullptr) {
StreamDfxManager::GetInstance().SendAudioErrorEvent(static_cast<int32_t>(getuid()),
RECORD_CALLBACK_ILLEGAL_STATE, "capturerinserver is null", false);
AUDIO_ERR_LOG("capturerinserver is null");
capturerLock.unlock();
return;
}
capturer->SetNonInterruptMute(muteFlag);
AUDIO_INFO_LOG("allCapturerMap_ has sessionId");
capturerLock.unlock();
UpdateSessionMuteStatus(sessionId, muteFlag);
return;
}
capturerLock.unlock();
SetNonInterruptMuteForProcess(sessionId, muteFlag);
}
void AudioService::SetNonInterruptMuteForProcess(const uint32_t sessionId, const bool muteFlag)
{
AUDIO_INFO_LOG("Cannot find sessionId");
if (!muteFlag) {
RemoveIdFromMuteControlSet(sessionId);
}
UpdateSessionMuteStatus(sessionId, muteFlag);
}
void AudioService::UpdateSessionMuteStatus(const uint32_t sessionId, const bool muteFlag)
{
std::lock_guard<std::mutex> muteSwitchStreamLock(muteSwitchStreamSetMutex_);
if (muteFlag) {
muteSwitchStreams_.insert(sessionId);
AUDIO_INFO_LOG("Insert into muteSwitchStreams_");
} else if (muteSwitchStreams_.count(sessionId)) {
muteSwitchStreams_.erase(sessionId);
}
}
int32_t AudioService::SetOffloadMode(uint32_t sessionId, int32_t state, bool isAppBack)
{
std::unique_lock<std::mutex> lock(rendererMapMutex_);
if (!allRendererMap_.count(sessionId)) {
StreamDfxManager::GetInstance().SendAudioErrorEvent(INVALID_APP_UID,
PLAY_CREATE_INVALID_INDEX, "SetOffloadMode renderer not in map", false);
AUDIO_WARNING_LOG("Renderer %{public}u is not in map", sessionId);
return ERR_INVALID_INDEX;
}
AUDIO_INFO_LOG("Set offload mode for renderer %{public}u", sessionId);
std::shared_ptr<RendererInServer> renderer = allRendererMap_[sessionId].lock();
if (renderer == nullptr) {
StreamDfxManager::GetInstance().SendAudioErrorEvent(INVALID_APP_UID,
PLAY_CREATE_NULL_POINTER, "SetOffloadMode RendererInServer is nullptr", false);
AUDIO_WARNING_LOG("RendererInServer is nullptr");
lock.unlock();
return ERROR;
}
lock.unlock();
int32_t ret = renderer->SetOffloadMode(state, isAppBack);
return ret;
}
int32_t AudioService::UnsetOffloadMode(uint32_t sessionId)
{
std::unique_lock<std::mutex> lock(rendererMapMutex_);
if (!allRendererMap_.count(sessionId)) {
StreamDfxManager::GetInstance().SendAudioErrorEvent(INVALID_APP_UID,
PLAY_CREATE_INVALID_INDEX, "UnsetOffloadMode renderer not in map", false);
AUDIO_WARNING_LOG("Renderer %{public}u is not in map", sessionId);
return ERR_INVALID_INDEX;
}
AUDIO_INFO_LOG("Set offload mode for renderer %{public}u", sessionId);
std::shared_ptr<RendererInServer> renderer = allRendererMap_[sessionId].lock();
if (renderer == nullptr) {
StreamDfxManager::GetInstance().SendAudioErrorEvent(INVALID_APP_UID,
PLAY_CREATE_NULL_POINTER, "UnsetOffloadMode RendererInServer is nullptr", false);
AUDIO_WARNING_LOG("RendererInServer is nullptr");
lock.unlock();
return ERROR;
}
lock.unlock();
int32_t ret = renderer->UnsetOffloadMode();
return ret;
}
void AudioService::UpdateAudioSinkState(uint32_t sinkId, bool started)
{
std::unique_lock<std::mutex> lock(allRunningSinksMutex_);
if (started) {
CHECK_AND_RETURN_LOG(allRunningSinks_.find(sinkId) == allRunningSinks_.end(),
"Sink %{public}u already started", sinkId);
allRunningSinks_.insert(sinkId);
AUDIO_INFO_LOG("Sink %{public}u started", sinkId);
} else {
CHECK_AND_RETURN_LOG(allRunningSinks_.find(sinkId) != allRunningSinks_.end(),
"Sink %{public}u already stopped or not started", sinkId);
allRunningSinks_.erase(sinkId);
AUDIO_INFO_LOG("Sink %{public}u stopped", sinkId);
if (allRunningSinks_.empty()) {
allRunningSinksCV_.notify_all();
AUDIO_INFO_LOG("All sinks stop, continue to hibernate");
}
}
return;
}
void AudioService::CheckHibernateState(bool onHibernate)
{
std::unique_lock<std::mutex> lock(allRunningSinksMutex_);
onHibernate_ = onHibernate;
if (onHibernate) {
bool ret = true;
if (allRunningSinks_.empty()) {
AUDIO_INFO_LOG("No running sinks, sleep for 300ms and check again");
lock.unlock();
usleep(RECHECK_SINK_STATE_IN_US);
lock.lock();
CHECK_AND_RETURN_LOG(!allRunningSinks_.empty(), "No running sinks, continue to hibernate");
}
AUDIO_INFO_LOG("Wait for all sinks to stop");
ret = allRunningSinksCV_.wait_for(lock, std::chrono::milliseconds(BLOCK_HIBERNATE_CALLBACK_IN_MS),
[this] {return (allRunningSinks_.empty() || !onHibernate_);});
if (!ret) {
AUDIO_ERR_LOG("On hibernate timeout, some sinks still running");
}
return;
} else {
allRunningSinksCV_.notify_all();
AUDIO_INFO_LOG("Wake up from hibernate");
}
}
bool AudioService::GetHibernateState()
{
std::unique_lock<std::mutex> lock(allRunningSinksMutex_);
return onHibernate_;
}
int32_t AudioService::UpdateSourceType(SourceType sourceType)
{
if (specialSourceTypeSet_.count(sourceType) != 0) {
return SUCCESS;
}
uint32_t id = HdiAdapterManager::GetInstance().GetId(HDI_ID_BASE_CAPTURE, HDI_ID_TYPE_PRIMARY);
std::shared_ptr<IAudioCaptureSource> source = HdiAdapterManager::GetInstance().GetCaptureSource(id);
CHECK_AND_RETURN_RET_LOG(source != nullptr, ERROR, "source is null");
return source->UpdateSourceType(sourceType);
}
void AudioService::SetIncMaxRendererStreamCnt(AudioMode audioMode)
{
if (audioMode == AUDIO_MODE_PLAYBACK) {
std::lock_guard<std::mutex> lock(streamLifeCycleMutex_);
currentRendererStreamCnt_++;
}
}
void AudioService::SetDecMaxRendererStreamCnt()
{
std::lock_guard<std::mutex> lock(streamLifeCycleMutex_);
currentRendererStreamCnt_--;
}
void AudioService::SetIncMaxLoopbackStreamCnt(AudioMode audioMode)
{
if (audioMode == AUDIO_MODE_PLAYBACK) {
currentLoopbackRendererStreamCnt_.fetch_add(1);
} else {
currentLoopbackCapturerStreamCnt_.fetch_add(1);
}
}
int32_t AudioService::GetCurrentLoopbackStreamCnt(AudioMode audioMode)
{
if (audioMode == AUDIO_MODE_PLAYBACK) {
return currentLoopbackRendererStreamCnt_.load();
} else {
return currentLoopbackCapturerStreamCnt_.load();
}
}
void AudioService::SetDecMaxLoopbackStreamCnt(AudioMode audioMode)
{
if (audioMode == AUDIO_MODE_PLAYBACK) {
currentLoopbackRendererStreamCnt_.fetch_sub(1);
} else {
currentLoopbackCapturerStreamCnt_.fetch_sub(1);
}
}
void AudioService::CleanAppUseNumMap(int32_t appUid)
{
std::lock_guard<std::mutex> lock(streamLifeCycleMutex_);
auto appUseNum = appUseNumMap_.find(appUid);
if (appUseNum != appUseNumMap_.end()) {
appUseNumMap_[appUid] = --appUseNum->second;
}
}
bool AudioService::HasBluetoothEndpoint()
{
return true;
}
int32_t AudioService::GetCurrentRendererStreamCnt()
{
std::lock_guard<std::mutex> lock(streamLifeCycleMutex_);
return currentRendererStreamCnt_;
}
void AudioService::GetAllSinkInputs(std::vector<SinkInput> &sinkInputs)
{
IStreamManager::GetPlaybackManager(PLAYBACK).GetAllSinkInputs(sinkInputs);
std::vector<SinkInput> directSinkInputs;
IStreamManager::GetPlaybackManager(DIRECT_PLAYBACK).GetAllSinkInputs(directSinkInputs);
sinkInputs.insert(sinkInputs.end(), directSinkInputs.begin(), directSinkInputs.end());
std::vector<SinkInput> voipSinkInputs;
IStreamManager::GetPlaybackManager(VOIP_PLAYBACK).GetAllSinkInputs(voipSinkInputs);
sinkInputs.insert(sinkInputs.end(), voipSinkInputs.begin(), voipSinkInputs.end());
}
bool AudioService::IsExceedingMaxStreamCntPerUid(int32_t callingUid, int32_t appUid,
int32_t maxStreamCntPerUid)
{
if (callingUid != MEDIA_SERVICE_UID) {
appUid = callingUid;
}
auto appUseNum = appUseNumMap_.find(appUid);
if (appUseNum != appUseNumMap_.end()) {
++appUseNum->second;
} else {
int32_t initValue = 1;
appUseNumMap_.emplace(appUid, initValue);
}
if (appUseNumMap_[appUid] > maxStreamCntPerUid) {
--appUseNumMap_[appUid];
int32_t mostAppUid = INVALID_APP_UID;
int32_t mostAppNum = INVALID_APP_CREATED_AUDIO_STREAM_NUM;
GetCreatedAudioStreamMostUid(mostAppUid, mostAppNum);
std::shared_ptr<Media::MediaMonitor::EventBean> bean = std::make_shared<Media::MediaMonitor::EventBean>(
Media::MediaMonitor::ModuleId::AUDIO, Media::MediaMonitor::EventId::AUDIO_STREAM_EXHAUSTED_STATS,
Media::MediaMonitor::EventType::FAULT_EVENT);
bean->Add("CLIENT_UID", mostAppUid);
bean->Add("TIMES", mostAppNum);
bean->Add("EXCEEDED_SCENE", "SingleApp");
Media::MediaMonitor::MediaMonitorManager::GetInstance().WriteLogMsg(bean);
HILOG_COMM_WARN("[IsExceedingMaxStreamCntPerUid]Current audio renderer stream num is greater "
"than the renderer stream num limit per uid");
return true;
}
return false;
}
void AudioService::GetCreatedAudioStreamMostUid(int32_t &mostAppUid, int32_t &mostAppNum)
{
std::lock_guard<std::mutex> lock(streamLifeCycleMutex_);
for (auto it = appUseNumMap_.begin(); it != appUseNumMap_.end(); it++) {
if (it->second > mostAppNum) {
mostAppNum = it->second;
mostAppUid = it->first;
}
}
return;
}
#ifdef HAS_FEATURE_INNERCAPTURER
int32_t AudioService::UnloadModernInnerCapSink(int32_t innerCapId)
{
return PolicyHandler::GetInstance().UnloadModernInnerCapSink(innerCapId);
}
int32_t AudioService::UnloadModernOffloadCapSource()
{
return PolicyHandler::GetInstance().UnloadModernOffloadCapSource();
}
#endif
RestoreStatus AudioService::RestoreSession(uint32_t sessionId, RestoreInfo restoreInfo)
{
{
std::lock_guard<std::mutex> lock(rendererMapMutex_);
if (allRendererMap_.find(sessionId) != allRendererMap_.end()) {
std::shared_ptr<RendererInServer> rendererInServer = allRendererMap_[sessionId].lock();
CHECK_AND_CALL_FUNC_RETURN_RET_LOG(rendererInServer != nullptr, RESTORE_ERROR,
StreamDfxManager::GetInstance().SendAudioErrorEvent(INVALID_APP_UID,
PLAY_CREATE_OPERATION_FAILED, "RestoreSession rendererInServer is null", false),
"Session could be released, restore failed");
return rendererInServer->RestoreSession(restoreInfo);
}
}
{
std::lock_guard<std::mutex> lock(capturerMapMutex_);
if (allCapturerMap_.find(sessionId) != allCapturerMap_.end()) {
std::shared_ptr<CapturerInServer> capturerInServer = allCapturerMap_[sessionId].lock();
CHECK_AND_CALL_FUNC_RETURN_RET_LOG(capturerInServer != nullptr, RESTORE_ERROR,
StreamDfxManager::GetInstance().SendAudioErrorEvent(static_cast<int32_t>(getuid()),
RECORD_CREATE_ILLEGAL_STATE, "Session could be released, restore failed", false),
"Session could be released, restore failed");
return capturerInServer->RestoreSession(restoreInfo);
}
}
StreamDfxManager::GetInstance().SendAudioErrorEvent(INVALID_APP_UID,
PLAY_CREATE_OPERATION_FAILED, "RestoreSession session not exists", false);
AUDIO_WARNING_LOG("Session not exists, restore failed");
return RESTORE_ERROR;
}
void AudioService::SaveAdjustStreamVolumeInfo(float volume, uint32_t sessionId, std::string adjustTime,
uint32_t code)
{
AudioVolume::GetInstance()->SaveAdjustStreamVolumeInfo(volume, sessionId, adjustTime, code);
}
void AudioService::RegisterMuteStateChangeCallback(uint32_t sessionId, const MuteStateChangeCallbck &callback)
{
std::unique_lock<std::mutex> lock(muteStateMapMutex_);
if (muteStateCallbacks_.count(sessionId) != 0) {
if (muteStateMap_.count(sessionId) != 0) {
AUDIO_INFO_LOG("session:%{public}u may start again, invoke callback now", sessionId);
bool flag = muteStateMap_[sessionId];
callback(flag);
} else {
AUDIO_WARNING_LOG("session:%{public}u mute state update failed...", sessionId);
}
}
muteStateCallbacks_[sessionId] = callback;
}
void AudioService::SetLatestMuteState(const uint32_t sessionId, const bool muteFlag)
{
std::unique_lock<std::mutex> lock(muteStateMapMutex_);
if (muteStateCallbacks_.count(sessionId) == 0) {
AUDIO_ERR_LOG("send mute flag to session:%{public}u failed", sessionId);
return;
}
if (muteFlag) {
muteStateMap_[sessionId] = muteFlag;
} else {
muteStateMap_.erase(sessionId);
}
AUDIO_INFO_LOG("session:%{public}u muteflag=%{public}d", sessionId, muteFlag ? 1 : 0);
muteStateCallbacks_[sessionId](muteFlag);
}
int32_t AudioService::ForceStopAudioStream(StopAudioType audioType)
{
CHECK_AND_RETURN_RET_LOG(audioType >= STOP_ALL && audioType <= STOP_RECORD, ERR_INVALID_PARAM, "Invalid audioType");
AUDIO_INFO_LOG("stop audio stream, type:%{public}d", audioType);
if (audioType == StopAudioType::STOP_ALL || audioType == StopAudioType::STOP_RENDER) {
std::lock_guard<std::mutex> lock(rendererMapMutex_);
for (auto &rendererMap : allRendererMap_) {
std::shared_ptr<RendererInServer> rendererInServer = rendererMap.second.lock();
CHECK_AND_CONTINUE_LOG(rendererInServer != nullptr, "stream could be released, no need to stop");
rendererInServer->StopSession();
}
}
if (audioType == StopAudioType::STOP_ALL || audioType == StopAudioType::STOP_RECORD) {
std::lock_guard<std::mutex> lock(capturerMapMutex_);
for (auto &capturerMap : allCapturerMap_) {
std::shared_ptr<CapturerInServer> capturerInServer = capturerMap.second.lock();
CHECK_AND_CONTINUE_LOG(capturerInServer != nullptr, "stream could be released, no need to stop");
capturerInServer->StopSession();
}
}
return SUCCESS;
}
float AudioService::GetSystemVolumeForWorkgroup()
{
std::unique_lock<std::mutex> lock(audioWorkGroupSystemVolumeMutex_);
return audioWorkGroupSystemVolume_;
}
bool AudioService::IsStreamTypeFitWorkgroup(AudioStreamType streamType)
{
return (workgroupSupportStreamTypeSet_.find(streamType) !=
workgroupSupportStreamTypeSet_.end());
}
void AudioService::UpdateSystemVolumeForWorkgroup(AudioStreamType streamType, float volume)
{
AUDIO_INFO_LOG("[WorkgroupInServer] streamType:%{public}d, systemvolume:%{public}f", streamType, volume);
if (!IsStreamTypeFitWorkgroup(streamType)) {
return;
}
{
std::unique_lock<std::mutex> lock(audioWorkGroupSystemVolumeMutex_);
audioWorkGroupSystemVolume_ = volume;
}
std::vector<int32_t> pids = AudioResourceService::GetInstance()->GetProcessesOfAudioWorkgroup();
for (int32_t pid : pids) {
RenderersCheckForAudioWorkgroup(pid);
}
}
void AudioService::RenderersCheckForAudioWorkgroup(int32_t pid)
{
if (!AudioResourceService::GetInstance()->IsProcessInWorkgroup(pid)) {
return;
}
if (AudioResourceService::GetInstance()->IsProcessHasSystemPermission(pid)) {
return;
}
std::unordered_map<int32_t, std::unordered_map<int32_t, bool>> allRenderPerProcessMap;
{
std::unique_lock<std::mutex> lock(rendererMapMutex_);
for (auto it = allRendererMap_.begin(); it != allRendererMap_.end(); it++) {
std::shared_ptr<RendererInServer> renderer = it->second.lock();
if (renderer == nullptr) {
continue;
}
if (renderer->processConfig_.appInfo.appPid != pid) {
continue;
}
if (!IsStreamTypeFitWorkgroup(renderer->processConfig_.streamType)) {
continue;
}
allRenderPerProcessMap[pid][renderer->processConfig_.originalSessionId]
= renderer->CollectInfosForWorkgroup(GetSystemVolumeForWorkgroup());
}
}
for (const auto &outerPair : allRenderPerProcessMap) {
int32_t pid = outerPair.first;
const auto &innerMap = outerPair.second;
bool isAllowed = false;
for (const auto &innerPair : innerMap) {
if (innerPair.second) {
isAllowed = true;
break;
}
}
AudioResourceService::GetInstance()->WorkgroupRendererMonitor(pid, isAllowed);
}
}
void AudioService::InitAllDupBuffer(int32_t innerCapId)
{
#ifdef HAS_FEATURE_INNERCAPTURER
AUDIO_INFO_LOG("InitAllDupBuffer, innerCapId: %{public}d", innerCapId);
std::unique_lock<std::mutex> lock(rendererMapMutex_);
if (filteredRendererMap_.count(innerCapId)) {
for (size_t i = 0; i < filteredRendererMap_[innerCapId].size(); i++) {
std::shared_ptr<RendererInServer> renderer = filteredRendererMap_[innerCapId][i].lock();
if (renderer == nullptr) {
AUDIO_WARNING_LOG("Renderer is already released!");
continue;
}
if (ShouldBeInnerCap(renderer->processConfig_, innerCapId)) {
renderer->InitDupBuffer(innerCapId);
}
}
}
lock.unlock();
#endif
}
std::shared_ptr<RendererInServer> AudioService::GetRendererInServerBySessionId(const uint32_t sessionId)
{
std::lock_guard<std::mutex> lock(rendererMapMutex_);
CHECK_AND_RETURN_RET(allRendererMap_.count(sessionId) > 0, nullptr);
return allRendererMap_[sessionId].lock();
}
int32_t AudioService::GetPrivacyTypeForNormalStream(const uint32_t sessionId, AudioPrivacyType &privacyType)
{
auto rendererInServer = GetRendererInServerBySessionId(sessionId);
CHECK_AND_RETURN_RET(rendererInServer != nullptr, ERROR);
privacyType = rendererInServer->processConfig_.privacyType;
return SUCCESS;
}
int32_t AudioService::GetPrivacyType(const uint32_t sessionId, AudioPrivacyType &privacyType)
{
int32_t ret = GetPrivacyTypeForNormalStream(sessionId, privacyType);
CHECK_AND_RETURN_RET(ret != SUCCESS, ret);
StreamDfxManager::GetInstance().SendAudioErrorEvent(INVALID_APP_UID,
PLAY_CREATE_INVALID_INDEX, "GetPrivacyType sessionId not found", false);
AUDIO_ERR_LOG("%{public}u not found", sessionId);
return ERROR;
}
int32_t AudioService::EnableDualStream(const uint32_t sessionId, const std::string &dupSinkName)
{
std::lock_guard lock(dualStreamMutex_);
int32_t ret = EnableDualStreamForNormalStream(sessionId, dupSinkName);
CHECK_AND_RETURN_RET(ret != SUCCESS, ret);
AUDIO_ERR_LOG("%{public}u failed", sessionId);
return ERR_OPERATION_FAILED;
}
int32_t AudioService::DisableDualStream(const uint32_t sessionId)
{
std::lock_guard lock(dualStreamMutex_);
int32_t ret = DisableDualStreamForNormalStream(sessionId);
CHECK_AND_RETURN_RET(ret != SUCCESS, ret);
AUDIO_ERR_LOG("%{public}u failed", sessionId);
return ERR_OPERATION_FAILED;
}
int32_t AudioService::RequestUserPrivacyAuthority(uint32_t sessionId)
{
std::shared_ptr<CapturerInServer> capturerInServer = nullptr;
std::unique_lock<std::mutex> lock(capturerMapMutex_);
if (allCapturerMap_.count(sessionId)) {
capturerInServer = allCapturerMap_[sessionId].lock();
}
lock.unlock();
CHECK_AND_RETURN_RET_LOG(capturerInServer != nullptr, ERROR, "sessionid not in allCapturerMap");
return capturerInServer->RequestUserPrivacyAuthority(sessionId);
}
int32_t AudioService::ReportPlaybackCaptureUserChoice(uint32_t sessionId, bool choice)
{
std::shared_ptr<CapturerInServer> capturerInServer = nullptr;
std::unique_lock<std::mutex> lock(capturerMapMutex_);
if (allCapturerMap_.count(sessionId)) {
capturerInServer = allCapturerMap_[sessionId].lock();
}
lock.unlock();
CHECK_AND_CALL_FUNC_RETURN_RET_LOG(capturerInServer != nullptr, ERROR,
StreamDfxManager::GetInstance().SendAudioErrorEvent(static_cast<int32_t>(getuid()),
RECORD_QUERY_ILLEGAL_STATE, "sessionid not in allCapturerMap", false),
"sessionid not in allCapturerMap");
return capturerInServer->ReportPlaybackCaptureUserChoice(sessionId, choice);
}
void AudioService::SetAncoRecordingConfigChanged(const std::vector<std::string> &bundleNameList)
{
std::lock_guard<std::mutex> lock(capturerMapMutex_);
bool isAncoCapturerExist = false;
for (auto &capturerMap : allCapturerMap_) {
std::shared_ptr<CapturerInServer> capturerInServer = capturerMap.second.lock();
CHECK_AND_CONTINUE(capturerInServer != nullptr && capturerInServer->GetAppUid() == UID_AUDIO);
capturerInServer->HandleMultiAncoCapturer(bundleNameList);
isAncoCapturerExist = true;
}
AUDIO_ERR_LOG("isAncoCapturerExist: %{public}d", isAncoCapturerExist);
CHECK_AND_CALL_FUNC_RETURN(isAncoCapturerExist,
AudioPrivacyManagerInServer::GetInstance().UpdateActiveAncoCapturer(bundleNameList));
}
void AudioService::NotifySensitiveRecordPermit(uint32_t sessionId, bool isPermitted)
{
AUDIO_INFO_LOG("sessionId: %{public}u, isPermitted: %{public}d", sessionId, isPermitted);
std::unique_lock<std::mutex> capturerLock(capturerMapMutex_);
if (allCapturerMap_.count(sessionId)) {
std::shared_ptr<CapturerInServer> capturer = allCapturerMap_[sessionId].lock();
if (capturer == nullptr) {
AUDIO_ERR_LOG("capturerinserver is null");
return;
}
capturer->NotifySensitiveRecordPermit(isPermitted);
return;
}
AUDIO_INFO_LOG("Cannot find sessionId %{public}u in allCapturerMap_", sessionId);
}
}
}