blob: 0263db1d83bbb91af0f632c446e8748e9bc07fdc [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/developer/forensics/feedback/annotation_providers.h"
#include <memory>
#include <utility>
#include "src/developer/forensics/feedback/annotations/constants.h"
#include "src/developer/forensics/feedback/constants.h"
#include "src/lib/backoff/exponential_backoff.h"
#include "src/lib/timekeeper/system_clock.h"
namespace forensics::feedback {
namespace {
bool IncludesAnyInAllowlist(const std::set<std::string>& keys,
const std::set<std::string>& allowlist) {
return std::any_of(keys.begin(), keys.end(),
[&allowlist](const std::string& key) { return allowlist.contains(key); });
}
} // namespace
AnnotationProviders::AnnotationProviders(
async_dispatcher_t* dispatcher, std::shared_ptr<sys::ServiceDirectory> services,
std::set<std::string> allowlist, const std::set<std::string>& product_exclude_list,
Annotations static_annotations,
std::unique_ptr<CachedAsyncAnnotationProvider> device_id_provider)
: dispatcher_(dispatcher),
data_register_(kMaxNumNonPlatformAnnotations, kReservedAnnotationNamespaces,
kDataRegisterPath),
device_id_provider_(std::move(device_id_provider)),
annotation_manager_(dispatcher_, allowlist, static_annotations, &data_register_,
GetDynamicSyncProviders(services, allowlist),
GetStaticAsyncProviders(services, allowlist),
GetCachedAsyncProviders(services, allowlist),
GetDynamicAsyncProviders(services, allowlist), product_exclude_list) {
FX_CHECK(allowlist.size() <= kMaxNumPlatformAnnotations)
<< "Requesting " << allowlist.size() << " annotations when " << kMaxNumPlatformAnnotations
<< " are alloted for the platform";
if (allowlist.empty()) {
FX_LOGS(WARNING) << "Annotation allowlist is empty, no platform annotations will be collected";
}
}
fuchsia::feedback::ComponentDataRegister* AnnotationProviders::ComponentDataRegister() {
return &data_register_;
}
std::unique_ptr<backoff::Backoff> AnnotationProviders::AnnotationProviderBackoff() {
return std::unique_ptr<backoff::Backoff>(
new backoff::ExponentialBackoff(zx::min(1), 2u, zx::hour(1)));
}
std::vector<DynamicSyncAnnotationProvider*> AnnotationProviders::GetDynamicSyncProviders(
const std::shared_ptr<sys::ServiceDirectory>& services,
const std::set<std::string>& allowlist) {
std::vector<DynamicSyncAnnotationProvider*> providers;
if (IncludesAnyInAllowlist(TimeProvider::GetAnnotationKeys(), allowlist)) {
time_provider_ =
std::make_unique<TimeProvider>(dispatcher_, zx::unowned_clock(zx_utc_reference_get()),
std::make_unique<timekeeper::SystemClock>());
providers.push_back(time_provider_.get());
}
if (IncludesAnyInAllowlist(UIStateProvider::GetAnnotationKeys(), allowlist)) {
providers.push_back(GetOrConstructUIStateProvider(services));
}
return providers;
}
std::vector<StaticAsyncAnnotationProvider*> AnnotationProviders::GetStaticAsyncProviders(
const std::shared_ptr<sys::ServiceDirectory>& services,
const std::set<std::string>& allowlist) {
std::vector<StaticAsyncAnnotationProvider*> providers;
if (IncludesAnyInAllowlist(BoardInfoProvider::GetAnnotationKeys(), allowlist)) {
board_info_provider_ =
std::make_unique<BoardInfoProvider>(dispatcher_, services, AnnotationProviderBackoff());
providers.push_back(board_info_provider_.get());
}
if (IncludesAnyInAllowlist(ProductInfoProvider::GetAnnotationKeys(), allowlist)) {
product_info_provider_ =
std::make_unique<ProductInfoProvider>(dispatcher_, services, AnnotationProviderBackoff());
providers.push_back(product_info_provider_.get());
}
if (IncludesAnyInAllowlist(CurrentChannelProvider::GetAnnotationKeys(), allowlist)) {
current_channel_provider_ = std::make_unique<CurrentChannelProvider>(
dispatcher_, services, AnnotationProviderBackoff());
providers.push_back(current_channel_provider_.get());
}
return providers;
}
std::vector<CachedAsyncAnnotationProvider*> AnnotationProviders::GetCachedAsyncProviders(
const std::shared_ptr<sys::ServiceDirectory>& services,
const std::set<std::string>& allowlist) {
std::vector<CachedAsyncAnnotationProvider*> providers;
providers.push_back(device_id_provider_.get());
if (IncludesAnyInAllowlist(IntlProvider::GetAnnotationKeys(), allowlist)) {
intl_provider_ =
std::make_unique<IntlProvider>(dispatcher_, services, AnnotationProviderBackoff());
providers.push_back(intl_provider_.get());
}
if (IncludesAnyInAllowlist(UIStateProvider::GetAnnotationKeys(), allowlist)) {
providers.push_back(GetOrConstructUIStateProvider(services));
}
return providers;
}
std::vector<DynamicAsyncAnnotationProvider*> AnnotationProviders::GetDynamicAsyncProviders(
const std::shared_ptr<sys::ServiceDirectory>& services,
const std::set<std::string>& allowlist) {
std::vector<DynamicAsyncAnnotationProvider*> providers;
if (IncludesAnyInAllowlist(TargetChannelProvider::GetAnnotationKeys(), allowlist)) {
target_channel_provider_ =
std::make_unique<TargetChannelProvider>(dispatcher_, services, AnnotationProviderBackoff());
providers.push_back(target_channel_provider_.get());
}
return providers;
}
UIStateProvider* AnnotationProviders::GetOrConstructUIStateProvider(
const std::shared_ptr<sys::ServiceDirectory>& services) {
if (ui_state_provider_ == nullptr) {
ui_state_provider_ = std::make_unique<UIStateProvider>(
dispatcher_, services, std::make_unique<timekeeper::SystemClock>(),
AnnotationProviderBackoff());
}
return ui_state_provider_.get();
}
} // namespace forensics::feedback