blob: c489c4693dcd9fd3535b770ac7bc10107799f299 [file] [log] [blame]
// Copyright 2018 The Chromium OS 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 SHILL_POWER_MANAGER_H_
#define SHILL_POWER_MANAGER_H_
// This class instantiates a PowerManagerProxy and distributes power events to
// registered users. It also provides a means for calling methods on the
// PowerManagerProxy.
#include <memory>
#include <string>
#include <base/callback.h>
#include <base/cancelable_callback.h>
#include <linux/nl80211.h>
#include "shill/power_manager_proxy_interface.h"
namespace shill {
class ControlInterface;
class PowerManager : public PowerManagerProxyDelegate {
public:
// This callback is called prior to a suspend attempt. When it is OK for the
// system to suspend, this callback should call ReportSuspendReadiness().
using SuspendImminentCallback = base::Closure;
// This callback is called after the completion of a suspend attempt. The
// receiver should undo any pre-suspend work that was done by the
// SuspendImminentCallback.
// The receiver should be aware that it is possible to get a
// SuspendDoneCallback while processing a DarkSuspendImminentCallback. So,
// SuspendDoneCallback should be ready to run concurrently with (and in a
// sense override) the actions taken by DarkSuspendImminentCallback.
using SuspendDoneCallback = base::Closure;
// This callback is called at the beginning of a dark resume.
// The receiver should arrange for ReportDarkSuspendImminentReadiness() to be
// called when shill is ready to resuspend. In most cases,
// ReportDarkSuspendImminentReadiness will be called asynchronously.
using DarkSuspendImminentCallback = base::Closure;
// |control_itnerface| creates the PowerManagerProxy. Use a fake for testing.
// Note: |Start| should be called to initialize this object before using it.
explicit PowerManager(ControlInterface* control_interface);
PowerManager(const PowerManager&) = delete;
PowerManager& operator=(const PowerManager&) = delete;
~PowerManager() override;
bool suspending() const { return suspending_; }
bool in_dark_resume() const { return in_dark_resume_; }
int64_t suspend_duration_us() const { return suspend_duration_us_; }
// Starts the PowerManager: Registers a suspend delay with the power manager
// for |suspend_delay|. See PowerManagerProxyInterface::RegisterSuspendDelay()
// for information about |suspend_delay|.
// - |imminent_callback| will be invoked when a suspend attempt is commenced
// - |done_callback| will be invoked when the attempt is completed. Returns
// false on failure.
// - This object guarantees that a call to |imminent_callback| is followed by
// a call to |done_callback| (before any more calls to |imminent_callback|).
virtual void Start(
base::TimeDelta suspend_delay,
const SuspendImminentCallback& suspend_imminent_callback,
const SuspendDoneCallback& suspend_done_callback,
const DarkSuspendImminentCallback& dark_suspend_imminent_callback);
virtual void Stop();
// Report suspend readiness. If called when there is no suspend attempt
// active, this function will fail. Returns true if sucessfully reported to
// powerd.
virtual bool ReportSuspendReadiness();
// Report dark suspend readiness. See ReportSuspendReadiness for more details.
virtual bool ReportDarkSuspendReadiness();
// Record the wake reason for the current dark resume.
bool RecordDarkResumeWakeReason(const std::string& wake_reason);
virtual bool ChangeRegDomain(nl80211_dfs_regions domain);
// Methods inherited from PowerManagerProxyDelegate.
void OnSuspendImminent(int suspend_id) override;
void OnSuspendDone(int suspend_id, int64_t suspend_duration_us) override;
void OnDarkSuspendImminent(int suspend_id) override;
private:
friend class ManagerTest;
friend class PowerManagerTest;
friend class ServiceTest;
// Human-readable string describing the suspend delay that is registered
// with the power manager.
static const int kInvalidSuspendId;
static const char kSuspendDelayDescription[];
static const char kDarkSuspendDelayDescription[];
static const int kSuspendTimeoutMilliseconds;
// These functions track the power_manager daemon appearing/vanishing from the
// DBus connection.
void OnPowerManagerAppeared();
void OnPowerManagerVanished();
void NotifySuspendDone();
ControlInterface* control_interface_;
// The power manager proxy created by this class. It dispatches the inherited
// delegate methods of this object when changes in the power state occur.
std::unique_ptr<PowerManagerProxyInterface> power_manager_proxy_;
// The delay (in milliseconds) to request powerd to wait after a suspend
// notification is received. powerd will actually suspend the system at least
// |suspend_delay_| after the notification, if we do not
// |ReportSuspendReadiness| earlier.
base::TimeDelta suspend_delay_;
// powerd tracks each (dark) suspend delay requested (by different clients)
// using randomly generated unique |(dark)suspend_delay_id_|s.
bool suspend_delay_registered_;
int suspend_delay_id_;
bool dark_suspend_delay_registered_;
int dark_suspend_delay_id_;
// Callbacks from shill called by this object when:
// ... powerd notified us that a suspend is imminent.
SuspendImminentCallback suspend_imminent_callback_;
// ... powerd notified us that the suspend attempt has finished.
SuspendDoneCallback suspend_done_callback_;
// ... powerd notified us that a dark suspend is imminent. This means that we
// just entered dark resume.
DarkSuspendImminentCallback dark_suspend_imminent_callback_;
// Set to true by OnSuspendImminent() and to false by OnSuspendDone().
bool suspending_;
// Set to true if readiness to suspend has been reported, i.e. any action to
// perform before suspend has been completed.
bool suspend_ready_;
// Set to true if the suspend done callback should be deferred until after
// any action to perform before suspend has been completed, i.e. when a
// SuspendDone notification arrives before ReportSuspendReadiness() is
// called.
bool suspend_done_deferred_;
// Set to true by OnDarkSuspendImminent() and to false by OnSuspendDone().
bool in_dark_resume_;
int current_suspend_id_;
int current_dark_suspend_id_;
// Set to time spent in suspended state during the last suspend in
// OnSuspendDone() and reset to 0 by OnSuspendImminent()
int64_t suspend_duration_us_;
power_manager::WifiRegDomainDbus wifi_reg_domain_;
bool wifi_reg_domain_is_set;
};
} // namespace shill
#endif // SHILL_POWER_MANAGER_H_