blob: d3d1740e6d335c89f0385cbbf79c75fe2afb4b1d [file] [log] [blame]
// Copyright 2014 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 POWER_MANAGER_POWERD_SYSTEM_DARK_RESUME_H_
#define POWER_MANAGER_POWERD_SYSTEM_DARK_RESUME_H_
#include <map>
#include <string>
#include <vector>
#include <base/macros.h>
#include <base/time/time.h>
#include <base/timer/timer.h>
#include <base/files/file_path.h>
#include "power_manager/powerd/system/power_supply.h"
namespace power_manager {
class PrefsInterface;
namespace system {
// Returns information related to "dark resume", a mode where the system briefly
// resumes from suspend to check the battery level and possibly shut down
// automatically.
class DarkResumeInterface {
public:
enum Action {
// Suspend the system.
SUSPEND = 0,
// Shut the system down immediately.
SHUT_DOWN,
};
DarkResumeInterface() {}
virtual ~DarkResumeInterface() {}
// These methods bracket each suspend request. PrepareForSuspendRequest will
// schedule the dark resume callback if it is able to, and
// UndoPrepareForSuspendRequest will deschedule it if necessary.
virtual void PrepareForSuspendRequest() = 0;
virtual void UndoPrepareForSuspendRequest() = 0;
// Updates state in anticipation of the system suspending, returning the
// action that should be performed. If SUSPEND is returned, |suspend_duration|
// contains the duration for which the system should be suspended or an empty
// base::TimeDelta() if the caller should not try to set up a wake alarm. This
// may occur if the system should suspend indefinitely, or if DarkResume was
// successful in setting a wake alarm for some point in the future.
// This may be called more than once per suspend request.
virtual void GetActionForSuspendAttempt(
Action* action,
base::TimeDelta* suspend_duration) = 0;
// Reads the system state to see if it's in a dark resume.
virtual void HandleSuccessfulResume() = 0;
// Returns true if the system is currently in dark resume.
virtual bool InDarkResume() = 0;
// Returns true if dark resume is enabled on the system.
virtual bool IsEnabled() = 0;
};
// Real implementation of DarkResumeInterface that interacts with sysfs.
class DarkResume : public DarkResumeInterface {
public:
// Within a device directory, kPowerDir contains kActiveFile, kSourceFile, and
// kWakeupTypeFile.
static const char kPowerDir[];
static const char kActiveFile[];
static const char kSourceFile[];
static const char kWakeupTypeFile[];
// Strings to write to sysfs files to enable/disable dark resume functionality
// at the kernel level.
static const char kEnabled[];
static const char kDisabled[];
// Strings to write to sysfs device wakeup type files to enable dark resume
// behavior on wakeup by the device.
static const char kAutomatic[];
static const char kUnknown[];
DarkResume();
virtual ~DarkResume();
void set_legacy_state_path_for_testing(const base::FilePath& path) {
legacy_state_path_ = path;
}
void set_wakeup_state_path_for_testing(const base::FilePath& path) {
wakeup_state_path_ = path;
}
void set_timer_for_testing(scoped_ptr<base::Timer> timer) {
timer_ = timer.Pass();
}
Action next_action_for_testing() const {
return next_action_;
}
// Reads preferences on how long to suspend, what devices are affected by
// suspend, and what devices can wake the system up from suspend.
// Ownership of passed-in pointers remains with the caller.
void Init(PowerSupplyInterface* power_supply, PrefsInterface* prefs);
// DarkResumeInterface implementation:
void PrepareForSuspendRequest() override;
void UndoPrepareForSuspendRequest() override;
void GetActionForSuspendAttempt(Action* action,
base::TimeDelta* suspend_duration) override;
void HandleSuccessfulResume() override;
bool InDarkResume() override;
bool IsEnabled() override;
private:
// Fills |suspend_durations_|, returning false if the pref was unset or empty.
bool ReadSuspendDurationsPref();
// This enables functionality for dark resume in devices that are listed in
// the prefs_file. The base_file is the name of the sysfs file we are writing
// to to enable the functionality for dark resume. This includes whether the
// device should do something different during a dark resume or whether it is
// a wakeup source for dark resume.
void GetFiles(std::vector<base::FilePath>* files,
const std::string& pref_name,
const std::string& base_file);
// Writes the passed-in state to all the files in |files|.
void SetStates(const std::vector<base::FilePath>& files,
const std::string& state);
// Callback which updates the next action and reschedules itself based on the
// current power status.
void ScheduleBatteryCheck();
// Gets the length of time to resuspend for given the current battery level.
base::TimeDelta GetNextSuspendDuration();
// Calculates a new |next_action_| to take based on the current battery level,
// line power status, and shutdown threshold. |next_action_| will then be
// used on the next suspend to decide whether to shut down or not.
void UpdateNextAction();
// Are we currently in dark resume?
bool in_dark_resume_;
// Is dark resume enabled?
bool enabled_;
// Are we using the new wakeup_type sysfs interface for dark resume?
bool using_wakeup_type_;
PowerSupplyInterface* power_supply_;
PrefsInterface* prefs_;
// Timer used to schedule system wakeups and check if we need to shut down.
scoped_ptr<base::Timer> timer_;
// Two possible dark resume state paths.
base::FilePath legacy_state_path_;
base::FilePath wakeup_state_path_;
// File read to get the dark resume state.
base::FilePath state_path_;
// Battery percentage threshold at which the system should shut down after a
// dark resume.
double battery_shutdown_threshold_;
// How long the system should suspend (values) at a given battery percentage
// (keys).
typedef std::map<double, base::TimeDelta> SuspendMap;
SuspendMap suspend_durations_;
// What the next suspend-time action should be.
Action next_action_;
std::vector<base::FilePath> dark_resume_sources_;
std::vector<base::FilePath> dark_resume_devices_;
DISALLOW_COPY_AND_ASSIGN(DarkResume);
};
} // namespace system
} // namespace power_manager
#endif // POWER_MANAGER_POWERD_SYSTEM_DARK_RESUME_H_