blob: 337bec529f189ed5e035d2818da31e305de2ac72 [file]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_DEVELOPER_MEMORY_PRESSURE_SIGNALER_PRESSURE_NOTIFIER_H_
#define SRC_DEVELOPER_MEMORY_PRESSURE_SIGNALER_PRESSURE_NOTIFIER_H_
#include <fidl/fuchsia.feedback/cpp/fidl.h>
#include <fidl/fuchsia.memorypressure/cpp/fidl.h>
#include <vector>
#include "src/developer/memory/pressure_signaler/pressure_observer.h"
namespace pressure_signaler {
class PressureNotifier : public fidl::Server<fuchsia_memorypressure::Provider> {
public:
// This struct contains all the state related to a single registered watchers.
//
// Note: `proxy` needs an event handler to be initialized, which is why its initialization needs
// to be deferred.
struct WatcherState : public fidl::AsyncEventHandler<fuchsia_memorypressure::Watcher> {
public:
WatcherState(Level level_sent, PressureNotifier* notifier)
: level_sent(level_sent), notifier(notifier) {}
std::optional<fidl::Client<fuchsia_memorypressure::Watcher>> proxy;
Level level_sent;
bool needs_free = false;
bool pending_callback = false;
PressureNotifier* notifier;
void on_fidl_error(fidl::UnbindInfo info) override { notifier->ReleaseWatcher(this); }
};
explicit PressureNotifier(bool watch_for_changes, bool send_critical_pressure_crash_reports,
fidl::Client<fuchsia_feedback::CrashReporter> crash_reporter,
async_dispatcher_t* dispatcher = nullptr);
PressureNotifier(const PressureNotifier&) = delete;
PressureNotifier& operator=(const PressureNotifier&) = delete;
// fuchsia::memorypressure::Provider interface
void RegisterWatcher(RegisterWatcherRequest& request,
RegisterWatcherCompleter::Sync& completer) override;
// Notify watchers of a pressure level change.
void Notify();
// Notify watchers with a simulated memory pressure |level|. For diagnostic use by MemoryDebugger.
void DebugNotify(fuchsia_memorypressure::Level level) const;
private:
void PostLevelChange();
void ReleaseWatcher(WatcherState* watcher_state);
void OnLevelChangedCallback(WatcherState* watcher);
void NotifyWatcher(WatcherState* watcher, Level level);
bool CanGenerateNewCriticalCrashReports();
enum CrashReportType : uint8_t {
kImminentOOM,
kCritical,
};
void FileCrashReport(CrashReportType type);
async::TaskClosureMethod<PressureNotifier, &PressureNotifier::PostLevelChange> post_task_{this};
async_dispatcher_t* const provider_dispatcher_;
std::vector<std::unique_ptr<WatcherState>> watchers_;
PressureObserver observer_;
bool observed_normal_level_ = true;
zx::time prev_critical_crash_report_time_ = zx::time(ZX_TIME_INFINITE_PAST);
zx::duration critical_crash_report_interval_ = zx::min(30);
const bool send_critical_pressure_crash_reports_;
fidl::Client<fuchsia_feedback::CrashReporter> crash_reporter_;
friend class test::PressureNotifierUnitTest;
};
} // namespace pressure_signaler
#endif // SRC_DEVELOPER_MEMORY_PRESSURE_SIGNALER_PRESSURE_NOTIFIER_H_