Commit 9d728dd0 authored by Bailey Berro's avatar Bailey Berro Committed by Commit Bot

Add MemoryUsageObserver to SystemDataProvider

Enables clients to implement the MemoryUsageObserver interface and
register themselves as an observer in order to receive periodic updates
about the usage of memory on the device.

Example use - crrev.com/c/2424505

Bug: 1128204
Change-Id: I17eaf3b8eb58c287e96d8ff217d3356d3d84c06e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2439475Reviewed-by: default avatarZentaro Kavanagh <zentaro@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Auto-Submit: Bailey Berro <baileyberro@chromium.org>
Commit-Queue: Dominick Ng <dominickn@chromium.org>
Cr-Commit-Position: refs/heads/master@{#813040}
parent c9f69b5a
......@@ -31,6 +31,7 @@ using ProbeCategories = healthd::ProbeCategoryEnum;
constexpr int kBatteryHealthRefreshIntervalInSeconds = 60;
constexpr int kChargeStatusRefreshIntervalInSeconds = 15;
constexpr int kMemoryUsageRefreshIntervalInSeconds = 10;
constexpr int kMilliampsInAnAmp = 1000;
void PopulateBoardName(const healthd::SystemInfo& system_info,
......@@ -128,6 +129,12 @@ void PopulateBatteryHealth(const healthd::BatteryInfo& battery_info,
out_battery_health.charge_full_design_milliamp_hours;
}
void PopulateMemoryUsage(const healthd::MemoryInfo& memory_info,
mojom::MemoryUsage& out_memory_usage) {
out_memory_usage.total_memory_kib = memory_info.total_memory_kib;
out_memory_usage.free_memory_kib = memory_info.free_memory_kib;
out_memory_usage.available_memory_kib = memory_info.available_memory_kib;
}
} // namespace
SystemDataProvider::SystemDataProvider() {
......@@ -187,6 +194,20 @@ void SystemDataProvider::ObserveBatteryHealth(
UpdateBatteryHealth();
}
void SystemDataProvider::ObserveMemoryUsage(
mojo::PendingRemote<mojom::MemoryUsageObserver> observer) {
memory_usage_observers_.Add(std::move(observer));
if (!memory_usage_timer_->IsRunning()) {
memory_usage_timer_->Start(
FROM_HERE,
base::TimeDelta::FromSeconds(kMemoryUsageRefreshIntervalInSeconds),
base::BindRepeating(&SystemDataProvider::UpdateMemoryUsage,
base::Unretained(this)));
}
UpdateMemoryUsage();
}
void SystemDataProvider::PowerChanged(
const power_manager::PowerSupplyProperties& proto) {
if (battery_charge_status_observers_.empty()) {
......@@ -211,6 +232,11 @@ void SystemDataProvider::SetBatteryHealthTimerForTesting(
battery_health_timer_ = std::move(timer);
}
void SystemDataProvider::SetMemoryUsageTimerForTesting(
std::unique_ptr<base::RepeatingTimer> timer) {
memory_usage_timer_ = std::move(timer);
}
void SystemDataProvider::OnSystemInfoProbeResponse(
GetSystemInfoCallback callback,
healthd::TelemetryInfoPtr info_ptr) {
......@@ -301,6 +327,15 @@ void SystemDataProvider::UpdateBatteryHealth() {
base::Unretained(this)));
}
void SystemDataProvider::UpdateMemoryUsage() {
BindCrosHealthdProbeServiceIfNeccessary();
probe_service_->ProbeTelemetryInfo(
{ProbeCategories::kMemory},
base::BindOnce(&SystemDataProvider::OnMemoryUsageUpdated,
base::Unretained(this)));
}
void SystemDataProvider::OnBatteryChargeStatusUpdated(
const base::Optional<PowerSupplyProperties>& power_supply_properties,
healthd::TelemetryInfoPtr info_ptr) {
......@@ -359,6 +394,29 @@ void SystemDataProvider::OnBatteryHealthUpdated(
NotifyBatteryHealthObservers(battery_health);
}
void SystemDataProvider::OnMemoryUsageUpdated(
healthd::TelemetryInfoPtr info_ptr) {
mojom::MemoryUsagePtr memory_usage = mojom::MemoryUsage::New();
if (info_ptr.is_null()) {
LOG(ERROR) << "Null response from croshealthd::ProbeTelemetryInfo.";
NotifyMemoryUsageObservers(memory_usage);
memory_usage_timer_.reset();
return;
}
const healthd::MemoryInfo* memory_info = GetMemoryInfo(*info_ptr);
if (memory_info == nullptr) {
LOG(ERROR) << "No MemoryInfo in response from cros_healthd.";
NotifyMemoryUsageObservers(memory_usage);
memory_usage_timer_.reset();
return;
}
PopulateMemoryUsage(*memory_info, *memory_usage.get());
NotifyMemoryUsageObservers(memory_usage);
}
void SystemDataProvider::NotifyBatteryChargeStatusObservers(
const mojom::BatteryChargeStatusPtr& battery_charge_status) {
for (auto& observer : battery_charge_status_observers_) {
......@@ -373,6 +431,13 @@ void SystemDataProvider::NotifyBatteryHealthObservers(
}
}
void SystemDataProvider::NotifyMemoryUsageObservers(
const mojom::MemoryUsagePtr& memory_usage) {
for (auto& observer : memory_usage_observers_) {
observer->OnMemoryUsageUpdated(memory_usage.Clone());
}
}
void SystemDataProvider::BindCrosHealthdProbeServiceIfNeccessary() {
if (!probe_service_ || !probe_service_.is_connected()) {
cros_healthd::ServiceConnection::GetInstance()->GetProbeService(
......
......@@ -39,6 +39,8 @@ class SystemDataProvider : public mojom::SystemDataProvider,
override;
void ObserveBatteryHealth(
mojo::PendingRemote<mojom::BatteryHealthObserver> observer) override;
void ObserveMemoryUsage(
mojo::PendingRemote<mojom::MemoryUsageObserver> observer) override;
// PowerManagerClient::Observer:
void PowerChanged(const power_manager::PowerSupplyProperties& proto) override;
......@@ -49,6 +51,9 @@ class SystemDataProvider : public mojom::SystemDataProvider,
void SetBatteryHealthTimerForTesting(
std::unique_ptr<base::RepeatingTimer> timer);
void SetMemoryUsageTimerForTesting(
std::unique_ptr<base::RepeatingTimer> timer);
private:
void BindCrosHealthdProbeServiceIfNeccessary();
......@@ -66,12 +71,16 @@ class SystemDataProvider : public mojom::SystemDataProvider,
void UpdateBatteryHealth();
void UpdateMemoryUsage();
void NotifyBatteryChargeStatusObservers(
const mojom::BatteryChargeStatusPtr& battery_charge_status);
void NotifyBatteryHealthObservers(
const mojom::BatteryHealthPtr& battery_health);
void NotifyMemoryUsageObservers(const mojom::MemoryUsagePtr& memory_usage);
void OnBatteryChargeStatusUpdated(
const base::Optional<power_manager::PowerSupplyProperties>&
power_supply_properties,
......@@ -79,13 +88,17 @@ class SystemDataProvider : public mojom::SystemDataProvider,
void OnBatteryHealthUpdated(cros_healthd::mojom::TelemetryInfoPtr info_ptr);
void OnMemoryUsageUpdated(cros_healthd::mojom::TelemetryInfoPtr info_ptr);
mojo::Remote<cros_healthd::mojom::CrosHealthdProbeService> probe_service_;
mojo::RemoteSet<mojom::BatteryChargeStatusObserver>
battery_charge_status_observers_;
mojo::RemoteSet<mojom::BatteryHealthObserver> battery_health_observers_;
mojo::RemoteSet<mojom::MemoryUsageObserver> memory_usage_observers_;
std::unique_ptr<base::RepeatingTimer> battery_charge_status_timer_;
std::unique_ptr<base::RepeatingTimer> battery_health_timer_;
std::unique_ptr<base::RepeatingTimer> memory_usage_timer_;
};
} // namespace diagnostics
......
......@@ -183,7 +183,7 @@ void SetCrosHealthdBatteryInfoResponse(const std::string& vendor,
CreateCrosHealthdBatteryInfoResponse(vendor, charge_full_design);
SetProbeTelemetryInfoResponse(std::move(battery_info), /*cpu_info=*/nullptr,
/*memory_info=*/nullptr,
/*memory_info=*/nullptr);
/*system_info=*/nullptr);
}
void SetCrosHealthdBatteryChargeStatusResponse(double charge_now,
......@@ -192,7 +192,7 @@ void SetCrosHealthdBatteryChargeStatusResponse(double charge_now,
CreateCrosHealthdBatteryChargeStatusResponse(charge_now, current_now);
SetProbeTelemetryInfoResponse(std::move(battery_info), /*cpu_info=*/nullptr,
/*memory_info=*/nullptr,
/*memory_info=*/nullptr);
/*system_info=*/nullptr);
}
void SetCrosHealthdBatteryHealthResponse(double charge_full_now,
......@@ -203,7 +203,19 @@ void SetCrosHealthdBatteryHealthResponse(double charge_full_now,
charge_full_design, cycle_count);
SetProbeTelemetryInfoResponse(std::move(battery_info), /*cpu_info=*/nullptr,
/*memory_info=*/nullptr,
/*memory_info=*/nullptr);
/*system_info=*/nullptr);
}
void SetCrosHealthdMemoryUsageResponse(uint32_t total_memory_kib,
uint32_t free_memory_kib,
uint32_t available_memory_kib) {
cros_healthd::mojom::MemoryInfoPtr memory_info =
cros_healthd::mojom::MemoryInfo::New(total_memory_kib, free_memory_kib,
available_memory_kib,
/*page_faults_since_last_boot=*/0);
SetProbeTelemetryInfoResponse(/*battery_info=*/nullptr, /*cpu_info=*/nullptr,
/*memory_info=*/std::move(memory_info),
/*system_info=*/nullptr);
}
bool AreValidPowerTimes(int64_t time_to_full, int64_t time_to_empty) {
......@@ -315,6 +327,15 @@ void VerifyHealthResult(const mojom::BatteryHealthPtr& update,
EXPECT_EQ(expected_battery_wear_percentage, update->battery_wear_percentage);
}
void VerifyMemoryUsageResult(const mojom::MemoryUsagePtr& update,
uint32_t expected_total_memory_kib,
uint32_t expected_free_memory_kib,
uint32_t expected_available_memory_kib) {
EXPECT_EQ(expected_total_memory_kib, update->total_memory_kib);
EXPECT_EQ(expected_free_memory_kib, update->free_memory_kib);
EXPECT_EQ(expected_available_memory_kib, update->available_memory_kib);
}
} // namespace
struct FakeBatteryChargeStatusObserver
......@@ -345,6 +366,19 @@ struct FakeBatteryHealthObserver : public mojom::BatteryHealthObserver {
mojo::Receiver<mojom::BatteryHealthObserver> receiver{this};
};
struct FakeMemoryUsageObserver : public mojom::MemoryUsageObserver {
// mojom::MemoryUsageObserver
void OnMemoryUsageUpdated(mojom::MemoryUsagePtr status_ptr) override {
updates.emplace_back(std::move(status_ptr));
}
// Tracks calls to OnMemoryUsageUpdated. Each call adds an element to
// the vector.
std::vector<mojom::MemoryUsagePtr> updates;
mojo::Receiver<mojom::MemoryUsageObserver> receiver{this};
};
class SystemDataProviderTest : public testing::Test {
public:
SystemDataProviderTest() {
......@@ -559,5 +593,53 @@ TEST_F(SystemDataProviderTest, BatteryHealthObserver) {
charge_full_design, new_cycle_count);
}
TEST_F(SystemDataProviderTest, MemoryUsageObserver) {
// Setup Timer
auto timer = std::make_unique<base::MockRepeatingTimer>();
auto* timer_ptr = timer.get();
system_data_provider_->SetMemoryUsageTimerForTesting(std::move(timer));
// Setup initial data
const uint32_t total_memory_kib = 10000;
const uint32_t free_memory_kib = 2000;
const uint32_t available_memory_kib = 4000;
SetCrosHealthdMemoryUsageResponse(total_memory_kib, free_memory_kib,
available_memory_kib);
// Registering as an observer should trigger one update.
FakeMemoryUsageObserver memory_usage_observer;
system_data_provider_->ObserveMemoryUsage(
memory_usage_observer.receiver.BindNewPipeAndPassRemote());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, memory_usage_observer.updates.size());
VerifyMemoryUsageResult(memory_usage_observer.updates[0], total_memory_kib,
free_memory_kib, available_memory_kib);
// Firing the timer should trigger another.
timer_ptr->Fire();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(2u, memory_usage_observer.updates.size());
VerifyMemoryUsageResult(memory_usage_observer.updates[1], total_memory_kib,
free_memory_kib, available_memory_kib);
// Updating the information in Croshealthd does not trigger an update until
// the timer fires
const uint32_t new_available_memory_kib = available_memory_kib + 1000;
SetCrosHealthdMemoryUsageResponse(total_memory_kib, free_memory_kib,
new_available_memory_kib);
EXPECT_EQ(2u, memory_usage_observer.updates.size());
timer_ptr->Fire();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(3u, memory_usage_observer.updates.size());
VerifyMemoryUsageResult(memory_usage_observer.updates[2], total_memory_kib,
free_memory_kib, new_available_memory_kib);
}
} // namespace diagnostics
} // namespace chromeos
......@@ -63,6 +63,13 @@ struct BatteryHealth {
int8 battery_wear_percentage;
};
// Contains information about the usage of memory on the device.
struct MemoryUsage {
uint32 total_memory_kib;
uint32 available_memory_kib;
uint32 free_memory_kib;
};
// Implemented by clients that wish to be updated periodically about changes to
// the battery charge status.
interface BatteryChargeStatusObserver {
......@@ -82,6 +89,15 @@ interface BatteryHealthObserver {
OnBatteryHealthUpdated(BatteryHealth battery_health);
};
// Implemented by clients that wish to be updated periodically about the
// memory usage of the device.
interface MemoryUsageObserver {
// OnMemoryUsageUpdated calls can be triggered by either of 2 conditions:
// 1) A MemoryUsageObserver is registered with SystemDataProvider
// 2) A periodic update is sent by SystemDataProvider
OnMemoryUsageUpdated(MemoryUsage memory_usage);
};
// Provides telemetric information about the system. This API is exposed to the
// Diagnostics SWA.
interface SystemDataProvider {
......@@ -98,6 +114,9 @@ interface SystemDataProvider {
ObserveBatteryChargeStatus(
pending_remote<BatteryChargeStatusObserver> observer);
// Registers an observer of BatteryHealth inforamation.
// Registers an observer of BatteryHealth information.
ObserveBatteryHealth(pending_remote<BatteryHealthObserver> observer);
// Registers an observer of MemoryUsage information.
ObserveMemoryUsage(pending_remote<MemoryUsageObserver> observer);
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment