blob: 87a61053fd4e0d1749c9c047631370456ecd3ad9 [file] [log] [blame]
// Copyright 2020 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 "diagnostics/cros_healthd/fetch_aggregator.h"
#include <functional>
#include <iterator>
#include <map>
#include <utility>
#include <vector>
#include <base/callback.h>
#include <base/check.h>
#include <base/logging.h>
namespace diagnostics {
namespace {
namespace mojo_ipc = chromeos::cros_healthd::mojom;
} // namespace
FetchAggregator::FetchAggregator(Context* context)
: audio_fetcher_(context),
backlight_fetcher_(context),
battery_fetcher_(context),
bluetooth_fetcher_(context),
boot_performance_fetcher_(context),
bus_fetcher_(context),
cpu_fetcher_(context),
disk_fetcher_(context),
fan_fetcher_(context),
memory_fetcher_(context),
network_fetcher_(context),
stateful_partition_fetcher_(context),
system_fetcher_(context),
timezone_fetcher_(context),
tpm_fetcher_(context) {}
FetchAggregator::~FetchAggregator() = default;
void FetchAggregator::Run(
const std::vector<mojo_ipc::ProbeCategoryEnum>& categories_to_probe,
mojo_ipc::CrosHealthdProbeService::ProbeTelemetryInfoCallback callback) {
const auto& state =
CreateProbeState(categories_to_probe, std::move(callback));
auto& info = state->result;
for (const auto category : categories_to_probe) {
switch (category) {
case mojo_ipc::ProbeCategoryEnum::kBattery: {
WrapFetchProbeData(category, state, &info->battery_result,
battery_fetcher_.FetchBatteryInfo());
break;
}
case mojo_ipc::ProbeCategoryEnum::kCpu: {
WrapFetchProbeData(category, state, &info->cpu_result,
cpu_fetcher_.FetchCpuInfo());
break;
}
case mojo_ipc::ProbeCategoryEnum::kNonRemovableBlockDevices: {
WrapFetchProbeData(category, state, &info->block_device_result,
disk_fetcher_.FetchNonRemovableBlockDevicesInfo());
break;
}
case mojo_ipc::ProbeCategoryEnum::kTimezone: {
WrapFetchProbeData(category, state, &info->timezone_result,
timezone_fetcher_.FetchTimezoneInfo());
break;
}
case mojo_ipc::ProbeCategoryEnum::kMemory: {
WrapFetchProbeData(category, state, &info->memory_result,
memory_fetcher_.FetchMemoryInfo());
break;
}
case mojo_ipc::ProbeCategoryEnum::kBacklight: {
WrapFetchProbeData(category, state, &info->backlight_result,
backlight_fetcher_.FetchBacklightInfo());
break;
}
case mojo_ipc::ProbeCategoryEnum::kFan: {
fan_fetcher_.FetchFanInfo(base::BindOnce(
&FetchAggregator::WrapFetchProbeData<mojo_ipc::FanResultPtr>,
weak_factory_.GetWeakPtr(), category, std::cref(state),
&info->fan_result));
break;
}
case mojo_ipc::ProbeCategoryEnum::kStatefulPartition: {
WrapFetchProbeData(
category, state, &info->stateful_partition_result,
stateful_partition_fetcher_.FetchStatefulPartitionInfo());
break;
}
case mojo_ipc::ProbeCategoryEnum::kBluetooth: {
WrapFetchProbeData(category, state, &info->bluetooth_result,
bluetooth_fetcher_.FetchBluetoothInfo());
break;
}
case mojo_ipc::ProbeCategoryEnum::kSystem: {
WrapFetchProbeData(category, state, &info->system_result,
system_fetcher_.FetchSystemInfo());
break;
}
case mojo_ipc::ProbeCategoryEnum::kSystem2: {
WrapFetchProbeData(category, state, &info->system_result_v2,
system_fetcher_.FetchSystemInfoV2());
break;
}
case mojo_ipc::ProbeCategoryEnum::kNetwork: {
network_fetcher_.FetchNetworkInfo(base::BindOnce(
&FetchAggregator::WrapFetchProbeData<mojo_ipc::NetworkResultPtr>,
weak_factory_.GetWeakPtr(), category, std::cref(state),
&info->network_result));
break;
}
case mojo_ipc::ProbeCategoryEnum::kAudio: {
WrapFetchProbeData(category, state, &info->audio_result,
audio_fetcher_.FetchAudioInfo());
break;
}
case mojo_ipc::ProbeCategoryEnum::kBootPerformance: {
WrapFetchProbeData(
category, state, &info->boot_performance_result,
boot_performance_fetcher_.FetchBootPerformanceInfo());
break;
}
case mojo_ipc::ProbeCategoryEnum::kBus: {
WrapFetchProbeData(category, state, &info->bus_result,
bus_fetcher_.FetchBusDevices());
break;
}
case mojo_ipc::ProbeCategoryEnum::kTpm: {
tpm_fetcher_.FetchTpmInfo(base::BindOnce(
&FetchAggregator::WrapFetchProbeData<mojo_ipc::TpmResultPtr>,
weak_factory_.GetWeakPtr(), category, std::cref(state),
&info->tpm_result));
break;
}
}
}
}
const std::unique_ptr<FetchAggregator::ProbeState>&
FetchAggregator::CreateProbeState(
const std::vector<mojo_ipc::ProbeCategoryEnum>& categories_to_probe,
mojo_ipc::CrosHealthdProbeService::ProbeTelemetryInfoCallback callback) {
const auto [it, success] =
probe_states_.insert(std::make_unique<ProbeState>());
DCHECK(success);
const auto& state = *it;
DCHECK(state);
state->remaining_categories = std::set<mojo_ipc::ProbeCategoryEnum>(
categories_to_probe.begin(), categories_to_probe.end());
state->result = mojo_ipc::TelemetryInfo::New();
state->callback = std::move(callback);
return state;
}
template <class T>
void FetchAggregator::WrapFetchProbeData(
mojo_ipc::ProbeCategoryEnum category,
const std::unique_ptr<ProbeState>& state,
T* response_data,
T fetched_data) {
DCHECK(state);
DCHECK(response_data);
*response_data = std::move(fetched_data);
auto& remaining_categories = state->remaining_categories;
remaining_categories.erase(category);
// Check for any unfetched categories - if one exists, we can't run the
// callback yet.
if (!remaining_categories.empty())
return;
std::move(state->callback).Run(std::move(state->result));
probe_states_.erase(state);
}
} // namespace diagnostics