blob: ea23488b899dca0050a26a49880d4eff48001d1e [file] [log] [blame]
// Copyright 2021 The Chromium 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 "chrome/browser/ash/system/kernel_feature_manager.h"
#include <stdint.h>
#include <string>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/string_split.h"
#include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
#include "third_party/cros_system_api/dbus/debugd/dbus-constants.h"
namespace chromeos {
KernelFeatureManager::KernelFeatureManager(
DebugDaemonClient* debug_daemon_client)
: debug_daemon_client_(debug_daemon_client) {
debug_daemon_client_->WaitForServiceToBeAvailable(
base::BindOnce(&KernelFeatureManager::OnDebugDaemonReady,
weak_ptr_factory_.GetWeakPtr()));
}
KernelFeatureManager::~KernelFeatureManager() = default;
void KernelFeatureManager::OnDebugDaemonReady(bool service_is_ready) {
if (!service_is_ready) {
LOG(ERROR) << "debugd service not ready";
return;
}
// Initialize the system.
debug_daemon_ready_ = true;
GetKernelFeatureList();
}
void KernelFeatureManager::GetKernelFeatureList() {
debug_daemon_client_->GetKernelFeatureList(
base::BindOnce(&KernelFeatureManager::OnKernelFeatureList,
weak_ptr_factory_.GetWeakPtr()));
}
void KernelFeatureManager::OnKernelFeatureList(bool result,
const std::string& out) {
if (result) {
// Split the CSV into a feature list
kernel_feature_list_ = base::SplitString(out, ",", base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY);
if (!kernel_feature_list_.empty()) {
// Find out which of these features requested in Finch
EnableKernelFeatures();
return;
}
}
LOG(ERROR) << "Failed to get or parse kernel feature list from debugd.";
}
void KernelFeatureManager::EnableKernelFeatures() {
base::FeatureList* feature_list_ins = base::FeatureList::GetInstance();
DCHECK(feature_list_ins);
for (const auto& name : kernel_feature_list_) {
VLOG(1) << "Enabling kernel feature via debugd: " << name << std::endl;
base::FieldTrial* trial = base::FeatureList::GetInstance()
->GetAssociatedFieldTrialByFeatureName(name);
// Skip enabling features that are not a part of the field trial.
// Note: We don't support dynamic disabling of kernel features on the device
// right now. Requests to disable result in *only* the disabled group getting
// activated. The kernel default for the device is already disabled.
if (!trial) {
continue;
}
if (feature_list_ins->GetEnabledFieldTrialByFeatureName(name)) {
// Features marked as enabled need to be enabled on the device.
// The actual finch experiment will be activated in the dbus callback
// later once the feature is enabled on the device.
debug_daemon_client_->KernelFeatureEnable(
name, base::BindOnce(&KernelFeatureManager::OnKernelFeatureEnable,
weak_ptr_factory_.GetWeakPtr()));
} else {
// The device defaults to "disabled", so no need to send any dbus commands
// to disable. Just enable the field trial experiment for disabled group.
trial->group();
VLOG(1) << "Kernel experiment " << name << "activated as disabled.";
}
}
}
void KernelFeatureManager::OnKernelFeatureEnable(bool result,
const std::string& out) {
base::FieldTrial* trial = base::FeatureList::GetInstance()
->GetAssociatedFieldTrialByFeatureName(out);
DCHECK(!result || trial);
if (result) {
trial->group();
VLOG(1) << "Kernel experiment " << out << "activated as enabled.";
return;
}
VLOG(1) << "Kernel feature has not been activated: " << out;
}
} // namespace chromeos