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 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
// Copyright 2021 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_DBUS_MEMORY_PRESSURE_EVALUATOR_LINUX_H_
#define CHROME_BROWSER_DBUS_MEMORY_PRESSURE_EVALUATOR_LINUX_H_
#include <memory>
#include <string>
#include "base/functional/callback_forward.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "components/memory_pressure/system_memory_pressure_evaluator.h"
#include "dbus/bus.h"
namespace dbus {
class Response;
class Signal;
} // namespace dbus
namespace memory_pressure {
class MemoryPressureVoter;
} // namespace memory_pressure
// A memory pressure evaluator that uses the low-memory-monitor service
// (abbreviated in the code as "LMM") to monitor the memory pressure. If the
// service is not available, it can use the XDG memory monitor portal as a
// fallback (which itself is a thin wrapper over LMM).
//
// The LMM API is described here:
// https://hadess.pages.freedesktop.org/low-memory-monitor/
// and the portal API wrapper is here:
// https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.MemoryMonitor
class DbusMemoryPressureEvaluatorLinux
: public memory_pressure::SystemMemoryPressureEvaluator {
public:
explicit DbusMemoryPressureEvaluatorLinux(
std::unique_ptr<memory_pressure::MemoryPressureVoter> voter);
~DbusMemoryPressureEvaluatorLinux() override;
DbusMemoryPressureEvaluatorLinux(const DbusMemoryPressureEvaluatorLinux&) =
delete;
DbusMemoryPressureEvaluatorLinux& operator=(
const DbusMemoryPressureEvaluatorLinux&) = delete;
private:
friend class DbusMemoryPressureEvaluatorLinuxTest;
friend class DbusMemoryPressureEvaluatorLinuxSignalConnectionTest;
// Constants for D-Bus services, object paths, methods, and signals. In-class
// so they can be shared with the tests.
static const char kMethodNameHasOwner[];
static const char kMethodListActivatableNames[];
static const char kLmmService[];
static const char kLmmObject[];
static const char kLmmInterface[];
static const char kXdgPortalService[];
static const char kXdgPortalObject[];
static const char kXdgPortalMemoryMonitorInterface[];
static const char kLowMemoryWarningSignal[];
static const base::TimeDelta kResetVotePeriod;
// The public constructor just delegates to this private one, but it's
// separated so that the test cases can pass in the mock bus instances.
DbusMemoryPressureEvaluatorLinux(
std::unique_ptr<memory_pressure::MemoryPressureVoter> voter,
scoped_refptr<dbus::Bus> system_bus,
scoped_refptr<dbus::Bus> session_bus);
// Checks if LMM itself is available, setting up the memory pressure signal
// handler if so. Otherwise, checks if the portal is available instead.
void CheckIfLmmIsAvailable();
// Handles the availability response from above.
void CheckIfLmmIsAvailableResponse(bool is_available);
// Checks if the portal service is available, setting up the memory pressure
// signal handler if so.
void CheckIfPortalIsAvailable();
// Handles the availability response from above.
void CheckIfPortalIsAvailableResponse(bool is_available);
// Checks if the given service is available, calling callback(true) if so or
// callback(false) otherwise.
void CheckIfServiceIsAvailable(scoped_refptr<dbus::Bus> bus,
const std::string& service,
base::OnceCallback<void(bool)> callback);
void OnNameHasOwnerResponse(scoped_refptr<dbus::Bus> bus,
const std::string& service,
base::OnceCallback<void(bool)> callback,
dbus::Response* response);
void OnListActivatableNamesResponse(const std::string& service,
base::OnceCallback<void(bool)> callback,
dbus::Response* response);
// Shuts down the given bus on the D-Bus thread and clears the pointer.
void ResetBus(scoped_refptr<dbus::Bus>& bus);
void OnSignalConnected(const std::string& interface,
const std::string& signal,
bool connected);
void OnLowMemoryWarning(dbus::Signal* signal);
// Converts a pressure level from LMM to base's memory pressure constants.
base::MemoryPressureListener::MemoryPressureLevel LmmToBasePressureLevel(
uint8_t lmm_level);
void UpdateLevel(base::MemoryPressureListener::MemoryPressureLevel new_level);
scoped_refptr<dbus::Bus> system_bus_;
scoped_refptr<dbus::Bus> session_bus_;
raw_ptr<dbus::ObjectProxy> object_proxy_ = nullptr;
// The values used to determine how to translate LMM memory pressure levels to
// Chrome's are stored here, gathered from feature params.
uint8_t moderate_level_;
uint8_t critical_level_;
// LMM never emits signals once the memory pressure has ended, so we need to
// estimate when that is the case by checking when the monitor has gone silent
// for a while.
base::OneShotTimer reset_vote_timer_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<DbusMemoryPressureEvaluatorLinux> weak_ptr_factory_{
this};
};
#endif // CHROME_BROWSER_DBUS_MEMORY_PRESSURE_EVALUATOR_LINUX_H_
|