blob: 76ff379867d316843e00c426da06f65c7b24224b [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 "power_manager/powerd/policy/input_controller.h"
#include <base/logging.h>
#include <chromeos/dbus/service_constants.h>
#include "power_manager/common/clock.h"
#include "power_manager/common/dbus_sender.h"
#include "power_manager/common/power_constants.h"
#include "power_manager/common/prefs.h"
#include "power_manager/common/util.h"
#include "power_manager/powerd/system/display/display_watcher.h"
#include "power_manager/powerd/system/input_watcher_interface.h"
#include "power_manager/proto_bindings/input_event.pb.h"
namespace power_manager {
namespace policy {
namespace {
// Frequency with which CheckActiveVT() should be called, in seconds.
// This just needs to be lower than the screen-dimming delay.
const int kCheckActiveVTFrequencySec = 60;
} // namespace
InputController::InputController()
: input_watcher_(NULL),
delegate_(NULL),
display_watcher_(NULL),
dbus_sender_(NULL),
clock_(new Clock),
only_has_external_display_(false),
lid_state_(LID_NOT_PRESENT) {
}
InputController::~InputController() {
if (input_watcher_)
input_watcher_->RemoveObserver(this);
}
void InputController::Init(system::InputWatcherInterface* input_watcher,
Delegate* delegate,
system::DisplayWatcherInterface* display_watcher,
DBusSenderInterface* dbus_sender,
PrefsInterface* prefs) {
input_watcher_ = input_watcher;
input_watcher_->AddObserver(this);
delegate_ = delegate;
display_watcher_ = display_watcher;
dbus_sender_ = dbus_sender;
prefs->GetBool(kExternalDisplayOnlyPref, &only_has_external_display_);
bool use_lid = false;
if (prefs->GetBool(kUseLidPref, &use_lid) && use_lid)
lid_state_ = input_watcher_->QueryLidState();
bool check_active_vt = false;
if (prefs->GetBool(kCheckActiveVTPref, &check_active_vt) && check_active_vt) {
check_active_vt_timer_.Start(FROM_HERE,
base::TimeDelta::FromSeconds(kCheckActiveVTFrequencySec),
this, &InputController::CheckActiveVT);
}
}
bool InputController::TriggerPowerButtonAcknowledgmentTimeoutForTesting() {
if (!power_button_acknowledgment_timer_.IsRunning())
return false;
power_button_acknowledgment_timer_.Stop();
HandlePowerButtonAcknowledgmentTimeout();
return true;
}
bool InputController::TriggerCheckActiveVTTimeoutForTesting() {
if (!check_active_vt_timer_.IsRunning())
return false;
CheckActiveVT();
return true;
}
void InputController::HandlePowerButtonAcknowledgment(
const base::TimeTicks& timestamp) {
VLOG(1) << "Received acknowledgment of power button press at "
<< timestamp.ToInternalValue() << "; expected "
<< expected_power_button_acknowledgment_timestamp_.ToInternalValue();
if (timestamp == expected_power_button_acknowledgment_timestamp_) {
delegate_->ReportPowerButtonAcknowledgmentDelay(clock_->GetCurrentTime() -
expected_power_button_acknowledgment_timestamp_);
expected_power_button_acknowledgment_timestamp_ = base::TimeTicks();
power_button_acknowledgment_timer_.Stop();
}
}
void InputController::OnLidEvent(LidState state) {
lid_state_ = state;
InputEvent proto;
switch (lid_state_) {
case LID_CLOSED:
delegate_->HandleLidClosed();
proto.set_type(InputEvent_Type_LID_CLOSED);
break;
case LID_OPEN:
delegate_->HandleLidOpened();
proto.set_type(InputEvent_Type_LID_OPEN);
break;
case LID_NOT_PRESENT:
return;
}
proto.set_timestamp(clock_->GetCurrentTime().ToInternalValue());
dbus_sender_->EmitSignalWithProtocolBuffer(kInputEventSignal, proto);
}
void InputController::OnPowerButtonEvent(ButtonState state) {
if (state == BUTTON_DOWN && only_has_external_display_ &&
display_watcher_->GetDisplays().empty()) {
delegate_->ShutDownForPowerButtonWithNoDisplay();
return;
}
if (state != BUTTON_REPEAT) {
const base::TimeTicks now = clock_->GetCurrentTime();
InputEvent proto;
proto.set_type(state == BUTTON_DOWN ?
InputEvent_Type_POWER_BUTTON_DOWN :
InputEvent_Type_POWER_BUTTON_UP);
proto.set_timestamp(now.ToInternalValue());
dbus_sender_->EmitSignalWithProtocolBuffer(kInputEventSignal, proto);
if (state == BUTTON_DOWN) {
expected_power_button_acknowledgment_timestamp_ = now;
power_button_acknowledgment_timer_.Start(FROM_HERE,
base::TimeDelta::FromMilliseconds(
kPowerButtonAcknowledgmentTimeoutMs),
this, &InputController::HandlePowerButtonAcknowledgmentTimeout);
} else {
expected_power_button_acknowledgment_timestamp_ = base::TimeTicks();
power_button_acknowledgment_timer_.Stop();
}
}
delegate_->HandlePowerButtonEvent(state);
}
void InputController::OnHoverStateChanged(bool hovering) {
delegate_->HandleHoverStateChanged(hovering);
}
void InputController::CheckActiveVT() {
if (input_watcher_->GetActiveVT() == 2)
delegate_->DeferInactivityTimeoutForVT2();
}
void InputController::HandlePowerButtonAcknowledgmentTimeout() {
delegate_->ReportPowerButtonAcknowledgmentDelay(
base::TimeDelta::FromMilliseconds(
kPowerButtonAcknowledgmentTimeoutMs));
delegate_->HandleMissingPowerButtonAcknowledgment();
expected_power_button_acknowledgment_timestamp_ = base::TimeTicks();
}
} // namespace policy
} // namespace power_manager