Skip to content

Commit

Permalink
arc: Introduce vmm swap scheduler
Browse files Browse the repository at this point in the history
This CL introduce a simple scheduler for execute swap.

(1) Must wait between two swaps. Use local storage to save the least
swap time.
(2) Check ARC running state regularly.

The scheduler will be enabled in different parameters by finch.

TEST=manually check will vmm-swap flag enabled

Bug: b:265383671
Change-Id: I8c0e004cec150cc8bdada26d8fc0e2aaba522f1d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4262294
Reviewed-by: Yuichiro Hanada <yhanada@chromium.org>
Commit-Queue: Shengsong Tan <sstan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1107315}
  • Loading branch information
Shengsong Tan authored and Chromium LUCI CQ committed Feb 20, 2023
1 parent b6aa987 commit 622c96c
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 0 deletions.
6 changes: 6 additions & 0 deletions ash/components/arc/arc_prefs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ const char kArcSnapshotHours[] = "arc.snapshot_hours";
// A preferece to keep ARC snapshot related info in dictionary.
const char kArcSnapshotInfo[] = "arc.snapshot";

// A time pref indicating the time in microseconds when ARCVM success executed
// vmm swap out. If it never swapped out, the pref holds the default value
// base::Time().
const char kArcVmmSwapOutTime[] = "arc_vmm_swap_out_time";

// A preference to keep track of whether or not Android WebView was used in the
// current ARC session.
const char kWebViewProcessStarted[] = "arc.webview.started";
Expand All @@ -161,6 +166,7 @@ void RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
registry->RegisterStringPref(kArcSerialNumberSalt, std::string());
registry->RegisterDictionaryPref(kArcSnapshotHours);
registry->RegisterDictionaryPref(kArcSnapshotInfo);
registry->RegisterTimePref(kArcVmmSwapOutTime, base::Time());
registry->RegisterDictionaryPref(kStabilityMetrics);

registry->RegisterIntegerPref(kAnrPendingCount, 0);
Expand Down
1 change: 1 addition & 0 deletions ash/components/arc/arc_prefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ ARC_EXPORT extern const char kAnrPendingDuration[];
ARC_EXPORT extern const char kArcSerialNumberSalt[];
ARC_EXPORT extern const char kArcSnapshotHours[];
ARC_EXPORT extern const char kArcSnapshotInfo[];
ARC_EXPORT extern const char kArcVmmSwapOutTime[];
ARC_EXPORT extern const char kStabilityMetrics[];
ARC_EXPORT extern const char kWebViewProcessStarted[];

Expand Down
3 changes: 3 additions & 0 deletions chrome/browser/ash/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,8 @@ source_set("ash") {
"arc/video/gpu_arc_video_service_host.h",
"arc/vmm/arc_vmm_manager.cc",
"arc/vmm/arc_vmm_manager.h",
"arc/vmm/arc_vmm_swap_scheduler.cc",
"arc/vmm/arc_vmm_swap_scheduler.h",
"arc/wallpaper/arc_wallpaper_service.cc",
"arc/wallpaper/arc_wallpaper_service.h",
"arc/window_predictor/arc_predictor_app_launch_handler.cc",
Expand Down Expand Up @@ -4952,6 +4954,7 @@ source_set("unit_tests") {
"arc/tracing/arc_value_event_unittest.cc",
"arc/tts/arc_tts_service_unittest.cc",
"arc/user_session/arc_user_session_service_unittest.cc",
"arc/vmm/arc_vmm_swap_scheduler_unittest.cc",
"arc/wallpaper/arc_wallpaper_service_unittest.cc",
"assistant/assistant_util_unittest.cc",
"attestation/attestation_ca_client_unittest.cc",
Expand Down
62 changes: 62 additions & 0 deletions chrome/browser/ash/arc/vmm/arc_vmm_swap_scheduler.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// 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 "ash/components/arc/arc_prefs.h"
#include "chrome/browser/ash/arc/vmm/arc_vmm_manager.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part.h"
#include "components/prefs/pref_service.h"

namespace arc {

namespace {

PrefService* local_state() {
return g_browser_process->local_state();
}
} // namespace

ArcVmmSwapScheduler::ArcVmmSwapScheduler(
base::TimeDelta minimum_swap_gap,
base::TimeDelta checking_period,
base::RepeatingCallback<bool()> swappable_checking_call,
base::RepeatingCallback<void(bool)> swap_call)
: minimum_swap_gap_(minimum_swap_gap),
checking_period_(checking_period),
swappable_checking_callback_(std::move(swappable_checking_call)),
swap_callback_(std::move(swap_call)) {}

ArcVmmSwapScheduler::~ArcVmmSwapScheduler() = default;

void ArcVmmSwapScheduler::Start() {
if (!timer_.IsRunning()) {
timer_.Start(FROM_HERE, checking_period_,
base::BindRepeating(&ArcVmmSwapScheduler::AttemptSwap,
weak_ptr_factory_.GetWeakPtr()));
}
}

void ArcVmmSwapScheduler::AttemptSwap() {
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_swap_gap_) {
return;
}
}

if (!swappable_checking_callback_.is_null() &&
swappable_checking_callback_.Run()) {
swap_callback_.Run(true);

// TODO(sstan): Should be set by swap out notify.
local_state()->SetTime(prefs::kArcVmmSwapOutTime, base::Time::Now());
}
}

} // namespace arc
45 changes: 45 additions & 0 deletions chrome/browser/ash/arc/vmm/arc_vmm_swap_scheduler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// 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.

#ifndef CHROME_BROWSER_ASH_ARC_VMM_ARC_VMM_SWAP_SCHEDULER_H_
#define CHROME_BROWSER_ASH_ARC_VMM_ARC_VMM_SWAP_SCHEDULER_H_

#include "base/functional/callback.h"
#include "base/timer/timer.h"

namespace arc {

// ArcVmmSwapScheduler periodically tries to swap out if it's suitable to enable
// VMM swap for ARCVM. It won't request to swap out within the given interval
// from the last swap out operation.
class ArcVmmSwapScheduler {
public:
ArcVmmSwapScheduler(base::TimeDelta minimum_swap_gap,
base::TimeDelta checking_period,
base::RepeatingCallback<bool()> swappable_checking_call,
base::RepeatingCallback<void(bool)> swap_call);
ArcVmmSwapScheduler(const ArcVmmSwapScheduler&) = delete;
ArcVmmSwapScheduler& operator=(const ArcVmmSwapScheduler&) = delete;
~ArcVmmSwapScheduler();

void Start();

private:
void AttemptSwap();

base::TimeDelta minimum_swap_gap_;
base::TimeDelta checking_period_;

base::RepeatingTimer timer_;

// Callback returns true if the current ARCVM state is swappable.
base::RepeatingCallback<bool()> swappable_checking_callback_;

// Callback sends swap status to vmm manager.
base::RepeatingCallback<void(bool)> swap_callback_;

base::WeakPtrFactory<ArcVmmSwapScheduler> weak_ptr_factory_{this};
};
} // namespace arc
#endif // CHROME_BROWSER_ASH_ARC_VMM_ARC_VMM_SWAP_SCHEDULER_H_
87 changes: 87 additions & 0 deletions chrome/browser/ash/arc/vmm/arc_vmm_swap_scheduler_unittest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// 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 "ash/components/arc/arc_prefs.h"
#include "ash/components/arc/session/arc_service_manager.h"
#include "base/test/bind.h"
#include "chrome/browser/ash/arc/vmm/arc_vmm_manager.h"
#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace arc {

namespace {
constexpr auto kSwapGap = base::Minutes(60);
constexpr auto kCheckingPreiod = base::Minutes(5);
} // namespace

class ArcVmmSwapSchedulerTest : public testing::Test {
public:
ArcVmmSwapSchedulerTest() : local_state_(TestingBrowserProcess::GetGlobal()) {
ash::ConciergeClient::InitializeFake();
}

ArcVmmSwapSchedulerTest(const ArcVmmSwapSchedulerTest&) = delete;
ArcVmmSwapSchedulerTest& operator=(const ArcVmmSwapSchedulerTest&) = delete;

~ArcVmmSwapSchedulerTest() override { ash::ConciergeClient::Shutdown(); }

void InitScheduler(base::RepeatingCallback<bool()> swappable_checking_call,
base::RepeatingCallback<void(bool)> swap_call) {
scheduler_ = std::make_unique<ArcVmmSwapScheduler>(
kSwapGap, kCheckingPreiod, swappable_checking_call, swap_call);
}

void SetSwapOutTime(base::Time time) {
local_state_.Get()->SetTime(prefs::kArcVmmSwapOutTime, base::Time());
}

base::test::TaskEnvironment* task_environment() { return &task_environment_; }

ArcVmmSwapScheduler* scheduler() { return scheduler_.get(); }

protected:
content::BrowserTaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};

private:
std::unique_ptr<ArcVmmSwapScheduler> scheduler_;

ScopedTestingLocalState local_state_;
};

TEST_F(ArcVmmSwapSchedulerTest, FirstSwap) {
// Pref value will be the base::Time() if it's empty.
SetSwapOutTime(base::Time());

int checking_count = 0, swap_count = 0;
InitScheduler(base::BindLambdaForTesting([&]() {
checking_count++;
return true;
}),
base::BindLambdaForTesting([&](bool enabled) {
if (enabled) {
swap_count++;
}
}));

scheduler()->Start();
base::RunLoop().RunUntilIdle();

// Checking should wait for the first period.
EXPECT_EQ(checking_count, 0);

// Check and swapped.
task_environment_.FastForwardBy(base::Minutes(20));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(checking_count, 1);
EXPECT_EQ(swap_count, 1);
}
} // namespace arc

0 comments on commit 622c96c

Please sign in to comment.