| // Copyright 2021 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. |
| |
| #ifndef CHROME_BROWSER_DBUS_MEMORY_PRESSURE_EVALUATOR_LINUX_H_ |
| #define CHROME_BROWSER_DBUS_MEMORY_PRESSURE_EVALUATOR_LINUX_H_ |
| |
| #include <memory> |
| #include <string> |
| |
| #include "base/callback_forward.h" |
| #include "base/memory/memory_pressure_listener.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_; |
| 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_ |