blob: 0a6249e1c41ab0a156d0f494d0f8dde9be782a89 [file] [log] [blame]
// Copyright (c) 2012 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.
#include <cstdlib>
#include <memory>
#include <string>
#include <sys/wait.h>
#include <unistd.h>
#include <base/at_exit.h>
#include <base/command_line.h>
#include <base/files/file_util.h>
#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/memory/ptr_util.h>
#include <base/message_loop/message_loop.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <brillo/flag_helper.h>
#include <metrics/metrics_library.h>
#include "power_manager/common/metrics_sender.h"
#include "power_manager/common/prefs.h"
#include "power_manager/common/util.h"
#include "power_manager/powerd/daemon.h"
#include "power_manager/powerd/daemon_delegate.h"
#include "power_manager/powerd/policy/external_backlight_controller.h"
#include "power_manager/powerd/policy/internal_backlight_controller.h"
#include "power_manager/powerd/policy/keyboard_backlight_controller.h"
#include "power_manager/powerd/system/acpi_wakeup_helper.h"
#include "power_manager/powerd/system/ambient_light_sensor.h"
#include "power_manager/powerd/system/audio_client.h"
#include "power_manager/powerd/system/dark_resume.h"
#include "power_manager/powerd/system/dbus_wrapper.h"
#include "power_manager/powerd/system/display/display_power_setter.h"
#include "power_manager/powerd/system/display/display_watcher.h"
#include "power_manager/powerd/system/ec_wakeup_helper.h"
#include "power_manager/powerd/system/event_device.h"
#include "power_manager/powerd/system/input_watcher.h"
#include "power_manager/powerd/system/internal_backlight.h"
#include "power_manager/powerd/system/peripheral_battery_watcher.h"
#include "power_manager/powerd/system/power_supply.h"
#include "power_manager/powerd/system/udev.h"
#ifndef VCSID
#define VCSID "<not set>"
#endif
namespace {
// Moves |latest_log_symlink| to |previous_log_symlink| and creates a relative
// symlink at |latest_log_symlink| pointing to |log_file|. All files must be in
// the same directory.
void UpdateLogSymlinks(const base::FilePath& latest_log_symlink,
const base::FilePath& previous_log_symlink,
const base::FilePath& log_file) {
CHECK_EQ(latest_log_symlink.DirName().value(), log_file.DirName().value());
base::DeleteFile(previous_log_symlink, false);
base::Move(latest_log_symlink, previous_log_symlink);
if (!base::CreateSymbolicLink(log_file.BaseName(), latest_log_symlink)) {
LOG(ERROR) << "Unable to create symbolic link from "
<< latest_log_symlink.value() << " to " << log_file.value();
}
}
std::string GetTimeAsString(time_t utime) {
struct tm tm;
CHECK_EQ(localtime_r(&utime, &tm), &tm);
char str[16];
CHECK_EQ(strftime(str, sizeof(str), "%Y%m%d-%H%M%S", &tm), 15UL);
return std::string(str);
}
} // namespace
namespace power_manager {
class DaemonDelegateImpl : public DaemonDelegate {
public:
DaemonDelegateImpl(const base::FilePath& read_write_prefs_dir,
const base::FilePath& read_only_prefs_dir)
: read_write_prefs_dir_(read_write_prefs_dir),
read_only_prefs_dir_(read_only_prefs_dir) {}
~DaemonDelegateImpl() override {}
// DaemonDelegate:
std::unique_ptr<PrefsInterface> CreatePrefs() override {
auto prefs = base::WrapUnique(new Prefs());
CHECK(prefs->Init(
util::GetPrefPaths(read_write_prefs_dir_, read_only_prefs_dir_)));
return std::move(prefs);
}
std::unique_ptr<system::DBusWrapperInterface> CreateDBusWrapper() override {
auto wrapper = base::WrapUnique(new system::DBusWrapper());
CHECK(wrapper->Init());
return std::move(wrapper);
}
std::unique_ptr<system::UdevInterface> CreateUdev() override {
auto udev = base::WrapUnique(new system::Udev());
CHECK(udev->Init());
return std::move(udev);
}
std::unique_ptr<system::AmbientLightSensorInterface>
CreateAmbientLightSensor() override {
auto sensor = base::WrapUnique(new system::AmbientLightSensor());
sensor->Init();
return std::move(sensor);
}
std::unique_ptr<system::DisplayWatcherInterface> CreateDisplayWatcher(
system::UdevInterface* udev) override {
auto watcher = base::WrapUnique(new system::DisplayWatcher());
watcher->Init(udev);
return std::move(watcher);
}
std::unique_ptr<system::DisplayPowerSetterInterface> CreateDisplayPowerSetter(
system::DBusWrapperInterface* dbus_wrapper) override {
auto setter = base::WrapUnique(new system::DisplayPowerSetter());
setter->Init(dbus_wrapper);
return std::move(setter);
}
std::unique_ptr<policy::BacklightController>
CreateExternalBacklightController(
system::DisplayWatcherInterface* display_watcher,
system::DisplayPowerSetterInterface* display_power_setter) override {
auto controller =
base::WrapUnique(new policy::ExternalBacklightController());
controller->Init(display_watcher, display_power_setter);
return std::move(controller);
}
std::unique_ptr<system::BacklightInterface> CreateInternalBacklight(
const base::FilePath& base_path,
const base::FilePath::StringType& pattern) override {
auto backlight = base::WrapUnique(new system::InternalBacklight());
if (!backlight->Init(base_path, pattern)) {
LOG(ERROR) << "Cannot initialize display backlight";
return std::unique_ptr<system::BacklightInterface>();
}
return std::move(backlight);
}
std::unique_ptr<policy::BacklightController>
CreateInternalBacklightController(
system::BacklightInterface* backlight,
PrefsInterface* prefs,
system::AmbientLightSensorInterface* sensor,
system::DisplayPowerSetterInterface* power_setter) override {
auto controller =
base::WrapUnique(new policy::InternalBacklightController());
controller->Init(backlight, prefs, sensor, power_setter);
return std::move(controller);
}
std::unique_ptr<policy::BacklightController>
CreateKeyboardBacklightController(
system::BacklightInterface* backlight,
PrefsInterface* prefs,
system::AmbientLightSensorInterface* sensor,
policy::BacklightController* display_backlight_controller,
TabletMode initial_tablet_mode) override {
auto controller =
base::WrapUnique(new policy::KeyboardBacklightController());
controller->Init(backlight, prefs, sensor, display_backlight_controller,
initial_tablet_mode);
return std::move(controller);
}
std::unique_ptr<system::InputWatcherInterface> CreateInputWatcher(
PrefsInterface* prefs,
system::UdevInterface* udev) override {
auto watcher = base::WrapUnique(new system::InputWatcher());
CHECK(watcher->Init(std::unique_ptr<system::EventDeviceFactoryInterface>(
new system::EventDeviceFactory),
prefs, udev));
return std::move(watcher);
}
std::unique_ptr<system::AcpiWakeupHelperInterface> CreateAcpiWakeupHelper()
override {
return base::WrapUnique(new system::AcpiWakeupHelper());
}
std::unique_ptr<system::EcWakeupHelperInterface> CreateEcWakeupHelper()
override {
return base::WrapUnique(new system::EcWakeupHelper());
}
std::unique_ptr<system::PeripheralBatteryWatcher>
CreatePeripheralBatteryWatcher(
system::DBusWrapperInterface* dbus_wrapper) override {
auto watcher = base::WrapUnique(new system::PeripheralBatteryWatcher());
watcher->Init(dbus_wrapper);
return watcher;
}
std::unique_ptr<system::PowerSupplyInterface> CreatePowerSupply(
const base::FilePath& power_supply_path,
PrefsInterface* prefs,
system::UdevInterface* udev) override {
auto supply = base::WrapUnique(new system::PowerSupply());
supply->Init(power_supply_path, prefs, udev,
true /* log_shutdown_thresholds */);
return std::move(supply);
}
std::unique_ptr<system::DarkResumeInterface> CreateDarkResume(
system::PowerSupplyInterface* power_supply,
PrefsInterface* prefs) override {
auto dark_resume = base::WrapUnique(new system::DarkResume());
dark_resume->Init(power_supply, prefs);
return std::move(dark_resume);
}
std::unique_ptr<system::AudioClientInterface> CreateAudioClient(
system::DBusWrapperInterface* dbus_wrapper) override {
auto client = base::WrapUnique(new system::AudioClient());
client->Init(dbus_wrapper);
return std::move(client);
}
std::unique_ptr<MetricsSenderInterface> CreateMetricsSender() override {
std::unique_ptr<MetricsLibrary> metrics_lib(new MetricsLibrary());
metrics_lib->Init();
return base::WrapUnique(new MetricsSender(std::move(metrics_lib)));
}
pid_t GetPid() override {
return getpid();
}
void Launch(const std::string& command) override {
LOG(INFO) << "Launching \"" << command << "\"";
pid_t pid = fork();
if (pid == 0) {
// TODO(derat): Is this setsid() call necessary?
setsid();
// fork() again and exit so that init becomes the command's parent and
// cleans up when it finally finishes.
exit(fork() == 0 ? ::system(command.c_str()) : 0);
} else if (pid > 0) {
// powerd cleans up after the originally-forked process, which exits
// immediately after forking again.
if (waitpid(pid, NULL, 0) == -1)
PLOG(ERROR) << "waitpid() on PID " << pid << " failed";
} else if (pid == -1) {
PLOG(ERROR) << "fork() failed";
}
}
int Run(const std::string& command) override {
LOG(INFO) << "Running \"" << command << "\"";
int return_value = ::system(command.c_str());
if (return_value == -1) {
PLOG(ERROR) << "fork() failed";
} else if (return_value) {
return_value = WEXITSTATUS(return_value);
LOG(ERROR) << "Command failed with exit status " << return_value;
}
return return_value;
}
private:
base::FilePath read_write_prefs_dir_;
base::FilePath read_only_prefs_dir_;
DISALLOW_COPY_AND_ASSIGN(DaemonDelegateImpl);
};
} // namespace power_manager
int main(int argc, char* argv[]) {
DEFINE_string(prefs_dir, power_manager::kReadWritePrefsDir,
"Directory holding read/write preferences.");
DEFINE_string(default_prefs_dir, power_manager::kReadOnlyPrefsDir,
"Directory holding read-only default settings.");
DEFINE_string(log_dir, "", "Directory where logs are written.");
DEFINE_string(run_dir, "", "Directory where stateful data is written.");
// This flag is handled by libbase/libchrome's logging library instead of
// directly by powerd, but it is defined here so FlagHelper won't abort after
// seeing an unexpected flag.
DEFINE_string(vmodule, "",
"Per-module verbose logging levels, e.g. \"foo=1,bar=2\"");
brillo::FlagHelper::Init(argc, argv,
"powerd, the Chromium OS userspace power manager.");
CHECK(!FLAGS_prefs_dir.empty()) << "--prefs_dir is required";
CHECK(!FLAGS_log_dir.empty()) << "--log_dir is required";
CHECK(!FLAGS_run_dir.empty()) << "--run_dir is required";
const base::FilePath log_file = base::FilePath(FLAGS_log_dir).Append(
base::StringPrintf("powerd.%s", GetTimeAsString(::time(NULL)).c_str()));
UpdateLogSymlinks(base::FilePath(FLAGS_log_dir).Append("powerd.LATEST"),
base::FilePath(FLAGS_log_dir).Append("powerd.PREVIOUS"),
log_file);
logging::LoggingSettings logging_settings;
logging_settings.logging_dest = logging::LOG_TO_FILE;
logging_settings.log_file = log_file.value().c_str();
logging_settings.lock_log = logging::DONT_LOCK_LOG_FILE;
logging::InitLogging(logging_settings);
LOG(INFO) << "vcsid " << VCSID;
base::AtExitManager at_exit_manager;
base::MessageLoopForIO message_loop;
// Extra parens to avoid http://en.wikipedia.org/wiki/Most_vexing_parse.
power_manager::DaemonDelegateImpl delegate(
(base::FilePath(FLAGS_prefs_dir)),
(base::FilePath(FLAGS_default_prefs_dir)));
power_manager::Daemon daemon(&delegate, (base::FilePath(FLAGS_run_dir)));
daemon.Init();
message_loop.Run();
return 0;
}