blob: 9b9c025da33b90c75a20287e94ea1f07fca39ae0 [file] [log] [blame]
// Copyright 2021 The Chromium OS 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 <string>
#include <utility>
#include <vector>
#include <chromeos/dbus/service_constants.h>
#include <cras/dbus-proxies.h>
#include "diagnostics/cros_healthd/fetchers/audio_fetcher.h"
#include "diagnostics/cros_healthd/utils/error_utils.h"
namespace diagnostics {
namespace {
namespace mojo_ipc = ::chromeos::cros_healthd::mojom;
} // namespace
mojo_ipc::AudioResultPtr AudioFetcher::FetchAudioInfo() {
mojo_ipc::AudioInfo info;
auto error = PopulateMuteInfo(&info);
if (error.has_value()) {
return mojo_ipc::AudioResult::NewError(std::move(error.value()));
}
error = PopulateActiveNodeInfo(&info);
if (error.has_value()) {
return mojo_ipc::AudioResult::NewError(std::move(error.value()));
}
return mojo_ipc::AudioResult::NewAudioInfo(info.Clone());
}
base::Optional<mojo_ipc::ProbeErrorPtr> AudioFetcher::PopulateMuteInfo(
mojo_ipc::AudioInfo* info) {
int32_t unused_output_volume;
bool output_mute = false; // Mute by other system daemons.
bool input_mute = false;
bool output_user_mute = false; // Mute by users.
brillo::ErrorPtr error;
if (!context_->cras_proxy()->GetVolumeState(&unused_output_volume,
&output_mute, &input_mute,
&output_user_mute, &error)) {
return CreateAndLogProbeError(
mojo_ipc::ErrorType::kSystemUtilityError,
"Failed retrieving mute info from cras: " + error->GetMessage());
}
info->output_mute = output_mute | output_user_mute;
info->input_mute = input_mute;
return base::nullopt;
}
base::Optional<mojo_ipc::ProbeErrorPtr> AudioFetcher::PopulateActiveNodeInfo(
mojo_ipc::AudioInfo* info) {
std::vector<brillo::VariantDictionary> nodes;
brillo::ErrorPtr error;
if (!context_->cras_proxy()->GetNodeInfos(&nodes, &error)) {
return CreateAndLogProbeError(
mojo_ipc::ErrorType::kSystemUtilityError,
"Failed retrieving node info from cras: " + error->GetMessage());
}
// There might be no active output / input device such as Chromebox.
info->output_device_name = std::string("No active output device");
info->output_volume = 0;
info->input_device_name = std::string("No active input device");
info->input_gain = 0;
info->underruns = 0;
info->severe_underruns = 0;
for (const auto& node : nodes) {
// Skip inactive node, or important fields are missing.
if (node.find(cras::kIsInputProperty) == node.end() ||
node.find(cras::kActiveProperty) == node.end() ||
!brillo::GetVariantValueOrDefault<bool>(node, cras::kActiveProperty)) {
continue;
}
if (!brillo::GetVariantValueOrDefault<bool>(node, cras::kIsInputProperty)) {
// Output node
info->output_device_name = brillo::GetVariantValueOrDefault<std::string>(
node, cras::kNameProperty);
info->output_volume = brillo::GetVariantValueOrDefault<uint64_t>(
node, cras::kNodeVolumeProperty);
if (node.find(cras::kNumberOfUnderrunsProperty) != node.end()) {
info->underruns = brillo::GetVariantValueOrDefault<uint32_t>(
node, cras::kNumberOfUnderrunsProperty);
}
if (node.find(cras::kNumberOfSevereUnderrunsProperty) != node.end()) {
info->severe_underruns = brillo::GetVariantValueOrDefault<uint32_t>(
node, cras::kNumberOfSevereUnderrunsProperty);
}
} else {
// Input node
info->input_device_name = brillo::GetVariantValueOrDefault<std::string>(
node, cras::kNameProperty);
info->input_gain = brillo::GetVariantValueOrDefault<uint32_t>(
node, cras::kInputNodeGainProperty);
}
}
return base::nullopt;
}
} // namespace diagnostics