blob: 13397fc23f81dcdfcc48deb7af7c58f4962d38b0 [file] [log] [blame]
// Copyright 2022 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/thermal_watcher.h"
#include <lib/syslog/cpp/macros.h>
#include <memory>
#include <rapidjson/document.h>
#include "fuchsia/thermal/cpp/fidl.h"
#include "lib/async/dispatcher.h"
#include "src/media/audio/audio_core/audio_device_manager.h"
#include "src/media/audio/audio_core/reporter.h"
#include "src/media/audio/audio_core/thermal_config.h"
namespace media::audio {
// Thermal Client
//
// static
std::unique_ptr<ThermalWatcher> ThermalWatcher::CreateAndWatch(Context& context) {
if (!context.process_config().thermal_config()) {
FX_LOGS(WARNING) << "No thermal configuration, so we won't start the thermal watcher";
return nullptr;
}
auto connector =
context.component_context().svc()->Connect<fuchsia::thermal::ClientStateConnector>();
fuchsia::thermal::ClientStateWatcherPtr watcher_request;
connector->Connect(
"audio", watcher_request.NewRequest(context.threading_model().FidlDomain().dispatcher()));
struct AccessToPrivateCtor : public ThermalWatcher {
AccessToPrivateCtor(fuchsia::thermal::ClientStateWatcherPtr state_watcher, Context& context)
: ThermalWatcher(std::move(state_watcher), context) {}
};
auto thermal_watcher = std::make_unique<AccessToPrivateCtor>(std::move(watcher_request), context);
thermal_watcher->WatchThermalState();
return thermal_watcher;
}
ThermalWatcher::ThermalWatcher(fuchsia::thermal::ClientStateWatcherPtr state_watcher,
Context& context)
: watcher_(std::move(state_watcher)),
dispatcher_(context.threading_model().FidlDomain().dispatcher()),
context_(context),
thermal_state_(0) {
FX_CHECK(watcher_);
auto thermal_config = context_.process_config().thermal_config();
if (thermal_config.states().empty()) {
FX_LOGS(ERROR) << "No thermal states, so we won't start the thermal watcher";
watcher_ = nullptr;
return;
}
watcher_.set_error_handler([this](zx_status_t status) {
FX_PLOGS(ERROR, status) << "Connection to fuchsia.thermal.ClientStateWatcher failed: ";
watcher_.set_error_handler(nullptr);
watcher_.Unbind();
});
}
void ThermalWatcher::WatchThermalState() {
if (!watcher_.is_bound()) {
return;
}
watcher_->Watch([this](uint64_t new_thermal_state) {
SetThermalState(new_thermal_state);
this->WatchThermalState();
});
}
void ThermalWatcher::SetThermalState(uint64_t state) {
if (thermal_state_ == state) {
if constexpr (kLogThermalStateChanges) {
FX_LOGS(INFO) << "No thermal state change (was already " << state << ")";
}
return;
}
for (auto& state_entry : context_.process_config().thermal_config().states()) {
if (state_entry.thermal_state_number() == state) {
for (auto& effect_config : state_entry.effect_configs()) {
async::PostTask(
context_.threading_model().FidlDomain().dispatcher(),
[this, name = effect_config.name(), target_config = effect_config.config_string(),
state]() {
this->context_.effects_controller()->UpdateEffect(
name, target_config,
[instance = name, config = target_config,
state](fuchsia::media::audio::EffectsController_UpdateEffect_Result result) {
if (result.is_err()) {
std::ostringstream err;
if (result.err() == fuchsia::media::audio::UpdateEffectError::NOT_FOUND) {
err << "effect with name '" << instance << "' was not found";
} else {
err << "message '" << config << "' was rejected";
}
if constexpr (kLogThermalEffectEnumeration) {
FX_LOGS(ERROR) << "Unable to apply thermal policy: " << err.str();
} else {
FX_LOGS_FIRST_N(ERROR, 500)
<< "Unable to apply thermal policy: " << err.str();
}
} else {
std::ostringstream out;
out << "Successfully updated effect '" << instance << "' for state " << state
<< " with config '" << config << "'";
if constexpr (kLogThermalEffectEnumeration) {
FX_LOGS(INFO) << out.str();
} else {
FX_LOGS(DEBUG) << out.str();
}
}
});
});
}
break;
}
}
auto previous_state = thermal_state_;
thermal_state_ = state;
Reporter::Singleton().SetThermalState(state);
if constexpr (kLogThermalStateChanges) {
FX_LOGS(INFO) << "Thermal state change (from " << previous_state << " to " << thermal_state_
<< ") has been posted";
}
}
} // namespace media::audio