1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
|
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ash/arc/vmm/arc_vmm_swap_scheduler.h"
#include <memory>
#include "base/functional/bind.h"
#include "chrome/browser/ash/arc/vmm/arc_system_state_observation.h"
#include "chrome/browser/ash/arc/vmm/arc_vmm_manager.h"
#include "chrome/browser/browser_process.h"
#include "chromeos/ash/experiences/arc/arc_prefs.h"
#include "chromeos/ash/experiences/arc/arc_util.h"
#include "components/prefs/pref_service.h"
#include "dbus/message.h"
namespace arc {
namespace {
PrefService* local_state() {
return g_browser_process->local_state();
}
} // namespace
ArcVmmSwapScheduler::ArcVmmSwapScheduler(
base::RepeatingCallback<void(bool)> swap_callback,
std::optional<base::TimeDelta> minimum_swapout_interval,
std::optional<base::TimeDelta> swappable_checking_period,
std::unique_ptr<PeaceDurationProvider> peace_duration_provider)
: swap_callback_(swap_callback) {
// Set callback to disable vmm-swap feature immdiately after the ARC get
// activated.
if (peace_duration_provider) {
peace_duration_provider->SetDurationResetCallback(
base::BindRepeating(&ArcVmmSwapScheduler::SetSwappable,
weak_ptr_factory_.GetWeakPtr(), false));
}
if (minimum_swapout_interval.has_value()) {
SetSwapoutThrottleInterval(minimum_swapout_interval.value());
}
if (swappable_checking_period.has_value()) {
SetActiveSwappableChecking(swappable_checking_period.value(),
std::move(peace_duration_provider));
}
auto* client = ash::ConciergeClient::Get();
if (client) {
vm_observer_.Observe(client);
}
}
ArcVmmSwapScheduler::~ArcVmmSwapScheduler() = default;
void ArcVmmSwapScheduler::SetSwappable(bool swappable) {
if (swappable) {
swap_callback_.Run(true);
} else {
swap_callback_.Run(false);
}
}
void ArcVmmSwapScheduler::OnVmSwapping(
const vm_tools::concierge::VmSwappingSignal& signal) {
if (signal.name() != kArcVmName) {
return;
}
if (signal.state() == vm_tools::concierge::SWAPPING_OUT) {
local_state()->SetTime(prefs::kArcVmmSwapOutTime, base::Time::Now());
}
}
void ArcVmmSwapScheduler::SetSwapoutThrottleInterval(base::TimeDelta interval) {
throttle_swapout_ = true;
minimum_swapout_interval_ = interval;
}
void ArcVmmSwapScheduler::SetActiveSwappableChecking(
base::TimeDelta period,
std::unique_ptr<PeaceDurationProvider> peace_duration_provider) {
DCHECK(peace_duration_provider);
swappable_checking_period_ = period;
peace_duration_provider_ = std::move(peace_duration_provider);
swappable_checking_timer_.Start(
FROM_HERE, period,
base::BindRepeating(
&ArcVmmSwapScheduler::UpdateSwappableStateByObservation,
weak_ptr_factory_.GetWeakPtr()));
}
void ArcVmmSwapScheduler::UpdateSwappableStateByObservation() {
if (throttle_swapout_) {
const base::Time last_swap_out_time =
local_state()->GetTime(prefs::kArcVmmSwapOutTime);
if (!last_swap_out_time.is_null()) {
auto past = base::Time::Now() - last_swap_out_time;
if (past < minimum_swapout_interval_) {
DVLOG(1) << "Swappable checking be throttled due to last swap on "
<< last_swap_out_time
<< " is not meet time interval requirement.";
return;
}
}
}
// Add some randomize for "enable" state. This way can make the state
// change in a uniform distribution [`swappable_checking_period_` * 0.5,
// `swappable_checking_period_` * 1.5].
SetSwappable(peace_duration_provider_->GetPeaceDuration() >
swappable_checking_period_ / 2);
}
} // namespace arc
|