blob: 652e31253a009f5fd7d577811bb028c91ea8c20c [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/media/audio/audio_core/audio_admin.h"
#include <fcntl.h>
#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include "src/media/audio/audio_core/audio_core_impl.h"
namespace media {
namespace audio {
AudioAdmin::AudioAdmin(AudioCoreImpl* service) : service_(service) {}
void AudioAdmin::SetInteraction(fuchsia::media::Usage active, fuchsia::media::Usage affected,
fuchsia::media::Behavior behavior) {
if (active.Which() == fuchsia::media::Usage::Tag::kCaptureUsage &&
affected.Which() == fuchsia::media::Usage::Tag::kCaptureUsage) {
active_rules_.SetRule(active.capture_usage(), affected.capture_usage(), behavior);
} else if (active.Which() == fuchsia::media::Usage::Tag::kCaptureUsage &&
affected.Which() == fuchsia::media::Usage::Tag::kRenderUsage) {
active_rules_.SetRule(active.capture_usage(), affected.render_usage(), behavior);
} else if (active.Which() == fuchsia::media::Usage::Tag::kRenderUsage &&
affected.Which() == fuchsia::media::Usage::Tag::kCaptureUsage) {
active_rules_.SetRule(active.render_usage(), affected.capture_usage(), behavior);
} else if (active.Which() == fuchsia::media::Usage::Tag::kRenderUsage &&
affected.Which() == fuchsia::media::Usage::Tag::kRenderUsage) {
active_rules_.SetRule(active.render_usage(), affected.render_usage(), behavior);
}
}
AudioAdmin::~AudioAdmin() { Shutdown(); }
zx_status_t AudioAdmin::Init() {
LoadDefaults();
return ZX_OK;
}
bool AudioAdmin::IsActive(fuchsia::media::AudioRenderUsage usage) {
auto usage_index = fidl::ToUnderlying(usage);
return active_streams_playback_[usage_index].size() > 0;
}
bool AudioAdmin::IsActive(fuchsia::media::AudioCaptureUsage usage) {
auto usage_index = fidl::ToUnderlying(usage);
return active_streams_capture_[usage_index].size() > 0;
}
void AudioAdmin::SetUsageNone(fuchsia::media::AudioRenderUsage usage) {
service_->SetRenderUsageGainAdjustment(usage, none_gain_db_);
}
void AudioAdmin::SetUsageNone(fuchsia::media::AudioCaptureUsage usage) {
service_->SetCaptureUsageGainAdjustment(usage, none_gain_db_);
}
void AudioAdmin::SetUsageMute(fuchsia::media::AudioRenderUsage usage) {
service_->SetRenderUsageGainAdjustment(usage, mute_gain_db_);
}
void AudioAdmin::SetUsageMute(fuchsia::media::AudioCaptureUsage usage) {
service_->SetCaptureUsageGainAdjustment(usage, mute_gain_db_);
}
void AudioAdmin::SetUsageDuck(fuchsia::media::AudioRenderUsage usage) {
service_->SetRenderUsageGainAdjustment(usage, duck_gain_db_);
}
void AudioAdmin::SetUsageDuck(fuchsia::media::AudioCaptureUsage usage) {
service_->SetCaptureUsageGainAdjustment(usage, duck_gain_db_);
}
void AudioAdmin::ApplyPolicies(fuchsia::media::AudioCaptureUsage active) {
for (int i = 0; i < fuchsia::media::RENDER_USAGE_COUNT; i++) {
auto affected = static_cast<fuchsia::media::AudioRenderUsage>(i);
switch (active_rules_.GetPolicy(active, affected)) {
case fuchsia::media::Behavior::NONE:
SetUsageNone(affected);
break;
case fuchsia::media::Behavior::DUCK:
SetUsageDuck(affected);
break;
case fuchsia::media::Behavior::MUTE:
SetUsageMute(affected);
break;
}
}
for (int i = 0; i < fuchsia::media::CAPTURE_USAGE_COUNT; i++) {
auto affected = static_cast<fuchsia::media::AudioCaptureUsage>(i);
switch (active_rules_.GetPolicy(active, affected)) {
case fuchsia::media::Behavior::NONE:
SetUsageNone(affected);
break;
case fuchsia::media::Behavior::DUCK:
SetUsageDuck(affected);
break;
case fuchsia::media::Behavior::MUTE:
SetUsageMute(affected);
break;
}
}
}
void AudioAdmin::ApplyPolicies(fuchsia::media::AudioRenderUsage active) {
for (int i = 0; i < fuchsia::media::RENDER_USAGE_COUNT; i++) {
auto affected = static_cast<fuchsia::media::AudioRenderUsage>(i);
switch (active_rules_.GetPolicy(active, affected)) {
case fuchsia::media::Behavior::NONE:
SetUsageNone(affected);
break;
case fuchsia::media::Behavior::DUCK:
SetUsageDuck(affected);
break;
case fuchsia::media::Behavior::MUTE:
SetUsageMute(affected);
break;
}
}
for (int i = 0; i < fuchsia::media::CAPTURE_USAGE_COUNT; i++) {
auto affected = static_cast<fuchsia::media::AudioCaptureUsage>(i);
switch (active_rules_.GetPolicy(active, affected)) {
case fuchsia::media::Behavior::NONE:
SetUsageNone(affected);
break;
case fuchsia::media::Behavior::DUCK:
SetUsageDuck(affected);
break;
case fuchsia::media::Behavior::MUTE:
SetUsageMute(affected);
break;
}
}
}
void AudioAdmin::UpdatePolicy() {
// TODO(perley): convert this to an array of Usage unions or something else
// that makes it at least a little flexible.
// The processing order of this represents the 'priorities' of the streams
// with this implementation.
if (IsActive(fuchsia::media::AudioCaptureUsage::COMMUNICATION)) {
ApplyPolicies(fuchsia::media::AudioCaptureUsage::COMMUNICATION);
} else if (IsActive(fuchsia::media::AudioRenderUsage::COMMUNICATION)) {
ApplyPolicies(fuchsia::media::AudioRenderUsage::COMMUNICATION);
} else if (IsActive(fuchsia::media::AudioCaptureUsage::SYSTEM_AGENT)) {
ApplyPolicies(fuchsia::media::AudioCaptureUsage::SYSTEM_AGENT);
} else if (IsActive(fuchsia::media::AudioRenderUsage::SYSTEM_AGENT)) {
ApplyPolicies(fuchsia::media::AudioRenderUsage::SYSTEM_AGENT);
} else if (IsActive(fuchsia::media::AudioRenderUsage::INTERRUPTION)) {
ApplyPolicies(fuchsia::media::AudioRenderUsage::INTERRUPTION);
} else if (IsActive(fuchsia::media::AudioCaptureUsage::FOREGROUND)) {
ApplyPolicies(fuchsia::media::AudioCaptureUsage::FOREGROUND);
} else if (IsActive(fuchsia::media::AudioRenderUsage::MEDIA)) {
ApplyPolicies(fuchsia::media::AudioRenderUsage::MEDIA);
} else if (IsActive(fuchsia::media::AudioCaptureUsage::BACKGROUND)) {
ApplyPolicies(fuchsia::media::AudioCaptureUsage::BACKGROUND);
} else {
ApplyPolicies(fuchsia::media::AudioRenderUsage::BACKGROUND);
}
}
void AudioAdmin::UpdateRendererState(fuchsia::media::AudioRenderUsage usage, bool active,
fuchsia::media::AudioRenderer* renderer) {
auto usage_index = fidl::ToUnderlying(usage);
FXL_DCHECK(usage_index < fuchsia::media::RENDER_USAGE_COUNT);
if (active) {
active_streams_playback_[usage_index].insert(renderer);
} else {
active_streams_playback_[usage_index].erase(renderer);
}
UpdatePolicy();
}
void AudioAdmin::UpdateCapturerState(fuchsia::media::AudioCaptureUsage usage, bool active,
fuchsia::media::AudioCapturer* capturer) {
auto usage_index = fidl::ToUnderlying(usage);
FXL_DCHECK(usage_index < fuchsia::media::CAPTURE_USAGE_COUNT);
if (active) {
active_streams_capture_[usage_index].insert(capturer);
} else {
active_streams_capture_[usage_index].erase(capturer);
}
UpdatePolicy();
}
void AudioAdmin::Shutdown() {}
void AudioAdmin::PolicyRules::ResetInteractions() {
for (int i = 0; i < fuchsia::media::RENDER_USAGE_COUNT; i++) {
auto active = static_cast<fuchsia::media::AudioRenderUsage>(i);
for (int j = 0; j < fuchsia::media::RENDER_USAGE_COUNT; j++) {
auto affected = static_cast<fuchsia::media::AudioRenderUsage>(j);
SetRule(active, affected, fuchsia::media::Behavior::NONE);
}
for (int j = 0; j < fuchsia::media::CAPTURE_USAGE_COUNT + 1; j++) {
auto affected = static_cast<fuchsia::media::AudioCaptureUsage>(j);
SetRule(active, affected, fuchsia::media::Behavior::NONE);
}
}
for (int i = 0; i < fuchsia::media::CAPTURE_USAGE_COUNT; i++) {
auto active = static_cast<fuchsia::media::AudioCaptureUsage>(i);
for (int j = 0; j < fuchsia::media::RENDER_USAGE_COUNT; j++) {
auto affected = static_cast<fuchsia::media::AudioRenderUsage>(j);
SetRule(active, affected, fuchsia::media::Behavior::NONE);
}
for (int j = 0; j < fuchsia::media::CAPTURE_USAGE_COUNT; j++) {
auto affected = static_cast<fuchsia::media::AudioCaptureUsage>(j);
SetRule(active, affected, fuchsia::media::Behavior::NONE);
}
}
}
} // namespace audio
} // namespace media