blob: 8e726392f1a88073d4a41622cf50965a4539f473 [file] [log] [blame]
// Copyright 2019 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/arc/instance_throttle/arc_instance_throttle.h"
#include <memory>
#include <string>
#include <vector>
#include "base/bind.h"
#include "base/command_line.h"
#include "chrome/browser/ash/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.h"
#include "chrome/browser/ash/arc/session/arc_session_manager.h"
#include "chrome/browser/ash/arc/test/test_arc_session_manager.h"
#include "chrome/browser/chromeos/throttle_observer.h"
#include "chrome/test/base/testing_profile.h"
#include "chromeos/dbus/concierge/concierge_client.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "components/arc/arc_features.h"
#include "components/arc/arc_prefs.h"
#include "components/arc/arc_service_manager.h"
#include "components/arc/mojom/power.mojom.h"
#include "components/arc/power/arc_power_bridge.h"
#include "components/arc/session/arc_bridge_service.h"
#include "components/arc/test/arc_util_test_support.h"
#include "components/arc/test/connection_holder_util.h"
#include "components/arc/test/fake_arc_session.h"
#include "components/arc/test/fake_power_instance.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/test/browser_task_environment.h"
#include "services/device/public/cpp/test/test_wake_lock_provider.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace arc {
class ArcInstanceThrottleTest : public testing::Test {
public:
ArcInstanceThrottleTest() = default;
~ArcInstanceThrottleTest() override = default;
ArcInstanceThrottleTest(const ArcInstanceThrottleTest&) = delete;
ArcInstanceThrottleTest& operator=(const ArcInstanceThrottleTest&) = delete;
void SetUp() override {
chromeos::PowerManagerClient::InitializeFake();
// Need to initialize DBusThreadManager before ArcSessionManager's
// constructor calls DBusThreadManager::Get().
chromeos::DBusThreadManager::Initialize();
chromeos::ConciergeClient::InitializeFake(/*fake_cicerone_client=*/nullptr);
arc_service_manager_ = std::make_unique<ArcServiceManager>();
arc_session_manager_ =
CreateTestArcSessionManager(std::make_unique<ArcSessionRunner>(
base::BindRepeating(FakeArcSession::Create)));
testing_profile_ = std::make_unique<TestingProfile>();
SetArcAvailableCommandLineForTesting(
base::CommandLine::ForCurrentProcess());
ArcBootPhaseMonitorBridge::GetForBrowserContextForTesting(
testing_profile_.get());
arc_instance_throttle_ =
ArcInstanceThrottle::GetForBrowserContextForTesting(
testing_profile_.get());
arc_instance_throttle_->set_delegate_for_testing(
std::make_unique<TestDelegateImpl>(this));
}
void TearDown() override {
DestroyPowerInstance();
testing_profile_.reset();
arc_session_manager_.reset();
arc_service_manager_.reset();
chromeos::ConciergeClient::Shutdown();
chromeos::DBusThreadManager::Shutdown();
chromeos::PowerManagerClient::Shutdown();
}
protected:
void CreatePowerInstance() {
ArcPowerBridge* const power_bridge =
ArcPowerBridge::GetForBrowserContextForTesting(testing_profile_.get());
DCHECK(power_bridge);
power_instance_ = std::make_unique<FakePowerInstance>();
arc_bridge_service()->power()->SetInstance(power_instance_.get());
WaitForInstanceReady(arc_bridge_service()->power());
}
void DestroyPowerInstance() {
if (!power_instance_)
return;
arc_bridge_service()->power()->CloseInstance(power_instance_.get());
power_instance_.reset();
}
sync_preferences::TestingPrefServiceSyncable* GetPrefs() {
return testing_profile_->GetTestingPrefService();
}
ArcBridgeService* arc_bridge_service() {
return arc_service_manager_->arc_bridge_service();
}
ArcInstanceThrottle* arc_instance_throttle() {
return arc_instance_throttle_;
}
FakePowerInstance* power_instance() { return power_instance_.get(); }
size_t disable_cpu_restriction_counter() const {
return disable_cpu_restriction_counter_;
}
size_t enable_cpu_restriction_counter() const {
return enable_cpu_restriction_counter_;
}
private:
class TestDelegateImpl : public ArcInstanceThrottle::Delegate {
public:
explicit TestDelegateImpl(ArcInstanceThrottleTest* test) : test_(test) {}
~TestDelegateImpl() override = default;
TestDelegateImpl(const TestDelegateImpl&) = delete;
TestDelegateImpl& operator=(const TestDelegateImpl&) = delete;
void SetCpuRestriction(CpuRestrictionState cpu_restriction_state) override {
switch (cpu_restriction_state) {
case CpuRestrictionState::CPU_RESTRICTION_FOREGROUND:
++(test_->disable_cpu_restriction_counter_);
break;
case CpuRestrictionState::CPU_RESTRICTION_BACKGROUND:
++(test_->enable_cpu_restriction_counter_);
break;
}
}
void RecordCpuRestrictionDisabledUMA(const std::string& observer_name,
base::TimeDelta delta) override {}
ArcInstanceThrottleTest* test_;
};
content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<ArcServiceManager> arc_service_manager_;
std::unique_ptr<ArcSessionManager> arc_session_manager_;
std::unique_ptr<TestingProfile> testing_profile_;
std::unique_ptr<FakePowerInstance> power_instance_;
ArcInstanceThrottle* arc_instance_throttle_;
size_t disable_cpu_restriction_counter_ = 0;
size_t enable_cpu_restriction_counter_ = 0;
};
// Tests that ArcInstanceThrottle can be constructed and destructed.
TEST_F(ArcInstanceThrottleTest, TestConstructDestruct) {}
// Tests that ArcInstanceThrottle adjusts ARC CPU restriction
// when ThrottleInstance is called.
TEST_F(ArcInstanceThrottleTest, TestThrottleInstance) {
arc_instance_throttle()->set_level_for_testing(
chromeos::ThrottleObserver::PriorityLevel::LOW);
EXPECT_EQ(1U, enable_cpu_restriction_counter());
EXPECT_EQ(0U, disable_cpu_restriction_counter());
// ArcInstanceThrottle level is already LOW, expect no change
arc_instance_throttle()->set_level_for_testing(
chromeos::ThrottleObserver::PriorityLevel::LOW);
EXPECT_EQ(1U, enable_cpu_restriction_counter());
EXPECT_EQ(0U, disable_cpu_restriction_counter());
arc_instance_throttle()->set_level_for_testing(
chromeos::ThrottleObserver::PriorityLevel::CRITICAL);
EXPECT_EQ(1U, enable_cpu_restriction_counter());
EXPECT_EQ(1U, disable_cpu_restriction_counter());
arc_instance_throttle()->set_level_for_testing(
chromeos::ThrottleObserver::PriorityLevel::LOW);
EXPECT_EQ(2U, enable_cpu_restriction_counter());
EXPECT_EQ(1U, disable_cpu_restriction_counter());
}
// Tests that power instance is correctly notified.
TEST_F(ArcInstanceThrottleTest, TestPowerNotification) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitWithFeatures({arc::kEnableThrottlingNotification},
{});
// Set power instance and it should be automatically notified once connection
// is made.
CreatePowerInstance();
EXPECT_EQ(1, power_instance()->cpu_restriction_state_count());
EXPECT_EQ(mojom::CpuRestrictionState::CPU_RESTRICTION_BACKGROUND,
power_instance()->last_cpu_restriction_state());
arc_instance_throttle()->set_level_for_testing(
chromeos::ThrottleObserver::PriorityLevel::CRITICAL);
EXPECT_EQ(2, power_instance()->cpu_restriction_state_count());
EXPECT_EQ(mojom::CpuRestrictionState::CPU_RESTRICTION_FOREGROUND,
power_instance()->last_cpu_restriction_state());
arc_instance_throttle()->set_level_for_testing(
chromeos::ThrottleObserver::PriorityLevel::LOW);
EXPECT_EQ(3, power_instance()->cpu_restriction_state_count());
EXPECT_EQ(mojom::CpuRestrictionState::CPU_RESTRICTION_BACKGROUND,
power_instance()->last_cpu_restriction_state());
}
// Tests that power instance notification is off by default.
TEST_F(ArcInstanceThrottleTest, TestPowerNotificationDisabledByDefault) {
// Set power instance and it should be automatically notified once connection
// is made.
CreatePowerInstance();
arc_instance_throttle()->set_level_for_testing(
chromeos::ThrottleObserver::PriorityLevel::CRITICAL);
arc_instance_throttle()->set_level_for_testing(
chromeos::ThrottleObserver::PriorityLevel::LOW);
EXPECT_EQ(0, power_instance()->cpu_restriction_state_count());
}
} // namespace arc