1 // Copyright 2021 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CHROME_BROWSER_DBUS_MEMORY_PRESSURE_EVALUATOR_LINUX_H_
6 #define CHROME_BROWSER_DBUS_MEMORY_PRESSURE_EVALUATOR_LINUX_H_
11 #include "base/functional/callback_forward.h"
12 #include "base/memory/memory_pressure_listener.h"
13 #include "base/memory/raw_ptr.h"
14 #include "base/memory/scoped_refptr.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/sequence_checker.h"
17 #include "base/time/time.h"
18 #include "base/timer/timer.h"
19 #include "components/memory_pressure/system_memory_pressure_evaluator.h"
27 namespace memory_pressure {
28 class MemoryPressureVoter;
29 } // namespace memory_pressure
31 // A memory pressure evaluator that uses the low-memory-monitor service
32 // (abbreviated in the code as "LMM") to monitor the memory pressure. If the
33 // service is not available, it can use the XDG memory monitor portal as a
34 // fallback (which itself is a thin wrapper over LMM).
36 // The LMM API is described here:
37 // https://hadess.pages.freedesktop.org/low-memory-monitor/
38 // and the portal API wrapper is here:
39 // https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.MemoryMonitor
40 class DbusMemoryPressureEvaluatorLinux
41 : public memory_pressure::SystemMemoryPressureEvaluator {
43 explicit DbusMemoryPressureEvaluatorLinux(
44 std::unique_ptr<memory_pressure::MemoryPressureVoter> voter);
45 ~DbusMemoryPressureEvaluatorLinux() override;
47 DbusMemoryPressureEvaluatorLinux(const DbusMemoryPressureEvaluatorLinux&) =
49 DbusMemoryPressureEvaluatorLinux& operator=(
50 const DbusMemoryPressureEvaluatorLinux&) = delete;
53 friend class DbusMemoryPressureEvaluatorLinuxTest;
54 friend class DbusMemoryPressureEvaluatorLinuxSignalConnectionTest;
56 // Constants for D-Bus services, object paths, methods, and signals. In-class
57 // so they can be shared with the tests.
58 static const char kMethodNameHasOwner[];
59 static const char kMethodListActivatableNames[];
61 static const char kLmmService[];
62 static const char kLmmObject[];
63 static const char kLmmInterface[];
65 static const char kXdgPortalService[];
66 static const char kXdgPortalObject[];
67 static const char kXdgPortalMemoryMonitorInterface[];
69 static const char kLowMemoryWarningSignal[];
71 static const base::TimeDelta kResetVotePeriod;
73 // The public constructor just delegates to this private one, but it's
74 // separated so that the test cases can pass in the mock bus instances.
75 DbusMemoryPressureEvaluatorLinux(
76 std::unique_ptr<memory_pressure::MemoryPressureVoter> voter,
77 scoped_refptr<dbus::Bus> system_bus,
78 scoped_refptr<dbus::Bus> session_bus);
80 // Checks if LMM itself is available, setting up the memory pressure signal
81 // handler if so. Otherwise, checks if the portal is available instead.
82 void CheckIfLmmIsAvailable();
83 // Handles the availability response from above.
84 void CheckIfLmmIsAvailableResponse(bool is_available);
86 // Checks if the portal service is available, setting up the memory pressure
87 // signal handler if so.
88 void CheckIfPortalIsAvailable();
89 // Handles the availability response from above.
90 void CheckIfPortalIsAvailableResponse(bool is_available);
92 // Checks if the given service is available, calling callback(true) if so or
93 // callback(false) otherwise.
94 void CheckIfServiceIsAvailable(scoped_refptr<dbus::Bus> bus,
95 const std::string& service,
96 base::OnceCallback<void(bool)> callback);
98 void OnNameHasOwnerResponse(scoped_refptr<dbus::Bus> bus,
99 const std::string& service,
100 base::OnceCallback<void(bool)> callback,
101 dbus::Response* response);
102 void OnListActivatableNamesResponse(const std::string& service,
103 base::OnceCallback<void(bool)> callback,
104 dbus::Response* response);
106 // Shuts down the given bus on the D-Bus thread and clears the pointer.
107 void ResetBus(scoped_refptr<dbus::Bus>& bus);
109 void OnSignalConnected(const std::string& interface,
110 const std::string& signal,
113 void OnLowMemoryWarning(dbus::Signal* signal);
115 // Converts a pressure level from LMM to base's memory pressure constants.
116 base::MemoryPressureListener::MemoryPressureLevel LmmToBasePressureLevel(
119 void UpdateLevel(base::MemoryPressureListener::MemoryPressureLevel new_level);
121 scoped_refptr<dbus::Bus> system_bus_;
122 scoped_refptr<dbus::Bus> session_bus_;
123 raw_ptr<dbus::ObjectProxy> object_proxy_ = nullptr;
125 // The values used to determine how to translate LMM memory pressure levels to
126 // Chrome's are stored here, gathered from feature params.
127 uint8_t moderate_level_;
128 uint8_t critical_level_;
130 // LMM never emits signals once the memory pressure has ended, so we need to
131 // estimate when that is the case by checking when the monitor has gone silent
133 base::OneShotTimer reset_vote_timer_;
135 SEQUENCE_CHECKER(sequence_checker_);
137 base::WeakPtrFactory<DbusMemoryPressureEvaluatorLinux> weak_ptr_factory_{
141 #endif // CHROME_BROWSER_DBUS_MEMORY_PRESSURE_EVALUATOR_LINUX_H_