// Copyright (c) 2013 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_event_handler.h"

#include <stdint.h>

#include <string>
#include <vector>

#include <base/format_macros.h>
#include <base/strings/stringprintf.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/message.h>
#include <gtest/gtest.h>

#include "power_manager/common/action_recorder.h"
#include "power_manager/common/clock.h"
#include "power_manager/common/fake_prefs.h"
#include "power_manager/common/power_constants.h"
#include "power_manager/powerd/system/dbus_wrapper_stub.h"
#include "power_manager/powerd/system/display/display_info.h"
#include "power_manager/powerd/system/display/display_watcher_stub.h"
#include "power_manager/powerd/system/input_watcher_stub.h"
#include "power_manager/proto_bindings/input_event.pb.h"
#include "power_manager/proto_bindings/switch_states.pb.h"

namespace power_manager {
namespace policy {
namespace {

const char kNoActions[] = "";
const char kLidClosed[] = "lid_closed";
const char kLidOpened[] = "lid_opened";
const char kPowerButtonDown[] = "power_down";
const char kPowerButtonUp[] = "power_up";
const char kPowerButtonRepeat[] = "power_repeat";
const char kShutDown[] = "shut_down";
const char kMissingPowerButtonAcknowledgment[] = "missing_power_button_ack";
const char kHoverOn[] = "hover_on";
const char kHoverOff[] = "hover_off";
const char kTabletOn[] = "tablet_on";
const char kTabletOff[] = "tablet_off";
const char kTabletUnsupported[] = "tablet_unsupported";

const char* GetTabletModeAction(TabletMode mode) {
  switch (mode) {
    case TabletMode::ON:
      return kTabletOn;
    case TabletMode::OFF:
      return kTabletOff;
    case TabletMode::UNSUPPORTED:
      return kTabletUnsupported;
  }
  NOTREACHED() << "Invalid tablet mode " << static_cast<int>(mode);
  return "tablet_invalid";
}

const char* GetPowerButtonAction(ButtonState state) {
  switch (state) {
    case ButtonState::DOWN:
      return kPowerButtonDown;
    case ButtonState::UP:
      return kPowerButtonUp;
    case ButtonState::REPEAT:
      return kPowerButtonRepeat;
  }
  NOTREACHED() << "Invalid power button state " << static_cast<int>(state);
  return "power_invalid";
}

std::string GetAcknowledgmentDelayAction(base::TimeDelta delay) {
  return base::StringPrintf("power_button_ack_delay(%" PRId64 ")",
                            delay.InMilliseconds());
}

class TestInputEventHandlerDelegate : public InputEventHandler::Delegate,
                                      public ActionRecorder {
 public:
  TestInputEventHandlerDelegate() {}
  ~TestInputEventHandlerDelegate() override {}

  // InputEventHandler::Delegate implementation:
  void HandleLidClosed() override { AppendAction(kLidClosed); }
  void HandleLidOpened() override { AppendAction(kLidOpened); }
  void HandlePowerButtonEvent(ButtonState state) override {
    AppendAction(GetPowerButtonAction(state));
  }
  void HandleHoverStateChange(bool hovering) override {
    AppendAction(hovering ? kHoverOn : kHoverOff);
  }
  void HandleTabletModeChange(TabletMode mode) override {
    EXPECT_NE(TabletMode::UNSUPPORTED, mode);
    AppendAction(GetTabletModeAction(mode));
  }
  void ShutDownForPowerButtonWithNoDisplay() override {
    AppendAction(kShutDown);
  }
  void HandleMissingPowerButtonAcknowledgment() override {
    AppendAction(kMissingPowerButtonAcknowledgment);
  }
  void ReportPowerButtonAcknowledgmentDelay(base::TimeDelta delay) override {
    AppendAction(GetAcknowledgmentDelayAction(delay));
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(TestInputEventHandlerDelegate);
};

}  // namespace

class InputEventHandlerTest : public ::testing::Test {
 public:
  InputEventHandlerTest() {
    handler_.clock_for_testing()->set_current_time_for_testing(
        base::TimeTicks::FromInternalValue(1000));
  }
  ~InputEventHandlerTest() override {}

 protected:
  // Initializes |handler_|.
  void Init() {
    handler_.Init(&input_watcher_, &delegate_, &display_watcher_,
                  &dbus_wrapper_, &prefs_);
  }

  // Tests that one InputEvent D-Bus signal has been sent and returns the
  // signal's |type| field.
  int GetInputEventSignalType() {
    InputEvent proto;
    EXPECT_EQ(1, dbus_wrapper_.num_sent_signals());
    EXPECT_TRUE(
        dbus_wrapper_.GetSentSignal(0, kInputEventSignal, &proto, nullptr));
    return proto.type();
  }

  // Tests that one InputEvent D-Bus signal has been sent and returns the
  // signal's |timestamp| field.
  int64_t GetInputEventSignalTimestamp() {
    InputEvent proto;
    EXPECT_EQ(1, dbus_wrapper_.num_sent_signals());
    EXPECT_TRUE(
        dbus_wrapper_.GetSentSignal(0, kInputEventSignal, &proto, nullptr));
    return proto.timestamp();
  }

  // Returns the current (fake) time.
  base::TimeTicks Now() {
    return handler_.clock_for_testing()->GetCurrentTime();
  }

  // Advances the current time by |interval|.
  void AdvanceTime(const base::TimeDelta& interval) {
    handler_.clock_for_testing()->set_current_time_for_testing(Now() +
                                                               interval);
  }

  // Makes an IgnoreNextPowerButtonPress D-Bus method call.
  void CallIgnoreNextPowerButtonPress(const base::TimeDelta& timeout) {
    dbus::MethodCall method_call(kPowerManagerInterface,
                                 kIgnoreNextPowerButtonPressMethod);
    dbus::MessageWriter(&method_call).AppendInt64(timeout.ToInternalValue());
    ASSERT_TRUE(dbus_wrapper_.CallExportedMethodSync(&method_call));
  }

  // Makes an HandlePowerButtonAcknowledgment D-Bus method call.
  void CallHandlePowerButtonAcknowledgment(const base::TimeTicks& timestamp) {
    dbus::MethodCall method_call(kPowerManagerInterface,
                                 kHandlePowerButtonAcknowledgmentMethod);
    dbus::MessageWriter(&method_call).AppendInt64(timestamp.ToInternalValue());
    ASSERT_TRUE(dbus_wrapper_.CallExportedMethodSync(&method_call));
  }

  FakePrefs prefs_;
  system::InputWatcherStub input_watcher_;
  system::DisplayWatcherStub display_watcher_;
  system::DBusWrapperStub dbus_wrapper_;
  TestInputEventHandlerDelegate delegate_;
  InputEventHandler handler_;
};

TEST_F(InputEventHandlerTest, LidEvents) {
  EXPECT_EQ(kNoActions, delegate_.GetActions());

  // Initialization shouldn't generate a synthetic event.
  prefs_.SetInt64(kUseLidPref, 1);
  Init();
  EXPECT_EQ(kNoActions, delegate_.GetActions());
  EXPECT_EQ(0, dbus_wrapper_.num_sent_signals());
  dbus_wrapper_.ClearSentSignals();

  AdvanceTime(base::TimeDelta::FromSeconds(1));
  input_watcher_.set_lid_state(LidState::CLOSED);
  input_watcher_.NotifyObserversAboutLidState();
  EXPECT_EQ(kLidClosed, delegate_.GetActions());
  EXPECT_EQ(InputEvent_Type_LID_CLOSED, GetInputEventSignalType());
  EXPECT_EQ(Now().ToInternalValue(), GetInputEventSignalTimestamp());
  dbus_wrapper_.ClearSentSignals();

  AdvanceTime(base::TimeDelta::FromSeconds(5));
  input_watcher_.set_lid_state(LidState::OPEN);
  input_watcher_.NotifyObserversAboutLidState();
  EXPECT_EQ(kLidOpened, delegate_.GetActions());
  EXPECT_EQ(InputEvent_Type_LID_OPEN, GetInputEventSignalType());
  EXPECT_EQ(Now().ToInternalValue(), GetInputEventSignalTimestamp());
  dbus_wrapper_.ClearSentSignals();
}

TEST_F(InputEventHandlerTest, TabletModeEvents) {
  Init();
  EXPECT_EQ(0, dbus_wrapper_.num_sent_signals());
  dbus_wrapper_.ClearSentSignals();

  AdvanceTime(base::TimeDelta::FromSeconds(1));
  input_watcher_.set_tablet_mode(TabletMode::ON);
  input_watcher_.NotifyObserversAboutTabletMode();
  EXPECT_EQ(kTabletOn, delegate_.GetActions());
  EXPECT_EQ(InputEvent_Type_TABLET_MODE_ON, GetInputEventSignalType());
  EXPECT_EQ(Now().ToInternalValue(), GetInputEventSignalTimestamp());
  dbus_wrapper_.ClearSentSignals();

  AdvanceTime(base::TimeDelta::FromSeconds(1));
  input_watcher_.set_tablet_mode(TabletMode::OFF);
  input_watcher_.NotifyObserversAboutTabletMode();
  EXPECT_EQ(kTabletOff, delegate_.GetActions());
  EXPECT_EQ(InputEvent_Type_TABLET_MODE_OFF, GetInputEventSignalType());
  EXPECT_EQ(Now().ToInternalValue(), GetInputEventSignalTimestamp());
  dbus_wrapper_.ClearSentSignals();
}

TEST_F(InputEventHandlerTest, PowerButtonEvents) {
  prefs_.SetInt64(kExternalDisplayOnlyPref, 1);
  std::vector<system::DisplayInfo> displays(1, system::DisplayInfo());
  display_watcher_.set_displays(displays);
  Init();

  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::DOWN);
  EXPECT_EQ(kPowerButtonDown, delegate_.GetActions());
  EXPECT_EQ(InputEvent_Type_POWER_BUTTON_DOWN, GetInputEventSignalType());
  EXPECT_EQ(Now().ToInternalValue(), GetInputEventSignalTimestamp());
  dbus_wrapper_.ClearSentSignals();

  AdvanceTime(base::TimeDelta::FromMilliseconds(100));
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::UP);
  EXPECT_EQ(kPowerButtonUp, delegate_.GetActions());
  EXPECT_EQ(InputEvent_Type_POWER_BUTTON_UP, GetInputEventSignalType());
  EXPECT_EQ(Now().ToInternalValue(), GetInputEventSignalTimestamp());
  dbus_wrapper_.ClearSentSignals();

  // With no displays connected, the system should shut down immediately.
  displays.clear();
  display_watcher_.set_displays(displays);
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::DOWN);
  EXPECT_EQ(kShutDown, delegate_.GetActions());
  EXPECT_EQ(0, dbus_wrapper_.num_sent_signals());
}

TEST_F(InputEventHandlerTest, IgnorePowerButtonPresses) {
  Init();
  dbus_wrapper_.ClearSentSignals();

  const base::TimeDelta kShortDelay = base::TimeDelta::FromMilliseconds(100);
  const base::TimeDelta kIgnoreTimeout = base::TimeDelta::FromSeconds(3);

  // Ignore the power button events.
  CallIgnoreNextPowerButtonPress(kIgnoreTimeout);
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::DOWN);
  EXPECT_TRUE(delegate_.GetActions().empty());
  EXPECT_EQ(0, dbus_wrapper_.num_sent_signals());

  // Release the power button.
  AdvanceTime(kShortDelay);
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::UP);
  EXPECT_TRUE(delegate_.GetActions().empty());
  EXPECT_EQ(0, dbus_wrapper_.num_sent_signals());

  // Next press is going through.
  AdvanceTime(kShortDelay);
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::DOWN);
  EXPECT_EQ(kPowerButtonDown, delegate_.GetActions());
  EXPECT_EQ(InputEvent_Type_POWER_BUTTON_DOWN, GetInputEventSignalType());
  dbus_wrapper_.ClearSentSignals();
  AdvanceTime(kShortDelay);
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::UP);
  EXPECT_EQ(kPowerButtonUp, delegate_.GetActions());
  EXPECT_EQ(InputEvent_Type_POWER_BUTTON_UP, GetInputEventSignalType());
  dbus_wrapper_.ClearSentSignals();

  // Ignore again the power button events.
  CallIgnoreNextPowerButtonPress(kIgnoreTimeout);
  // Expire the timeout.
  AdvanceTime(kIgnoreTimeout + base::TimeDelta::FromMilliseconds(500));
  // The next press is going through.
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::DOWN);
  EXPECT_EQ(kPowerButtonDown, delegate_.GetActions());
  AdvanceTime(kShortDelay);
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::UP);
  EXPECT_EQ(kPowerButtonUp, delegate_.GetActions());

  // Ignore again the power button events.
  CallIgnoreNextPowerButtonPress(kIgnoreTimeout);
  // Cancel the timeout.
  CallIgnoreNextPowerButtonPress(base::TimeDelta());
  // The next press is going through.
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::DOWN);
  EXPECT_EQ(kPowerButtonDown, delegate_.GetActions());
  AdvanceTime(kShortDelay);
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::UP);
  EXPECT_EQ(kPowerButtonUp, delegate_.GetActions());

  // Race condition between the user and the U2F code, the down event happens
  // before the ignore event.
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::DOWN);
  EXPECT_EQ(kPowerButtonDown, delegate_.GetActions());
  AdvanceTime(kShortDelay);
  // Then the daemon receives the request to ignore the physical presence on
  // the power button.
  CallIgnoreNextPowerButtonPress(kIgnoreTimeout);
  // The user release the button but the release needs to go through else we
  // have a press without a release (which becomes a long press).
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::UP);
  EXPECT_EQ(kPowerButtonUp, delegate_.GetActions());
}

TEST_F(InputEventHandlerTest, AcknowledgePowerButtonPresses) {
  Init();

  const base::TimeDelta kShortDelay = base::TimeDelta::FromMilliseconds(100);
  const base::TimeDelta kTimeout =
      InputEventHandler::kPowerButtonAcknowledgmentTimeout;

  // Press the power button, acknowledge the event nearly immediately, and check
  // that no further actions are performed and that the timeout is stopped.
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::DOWN);
  EXPECT_EQ(kPowerButtonDown, delegate_.GetActions());
  AdvanceTime(kShortDelay);
  CallHandlePowerButtonAcknowledgment(
      base::TimeTicks::FromInternalValue(GetInputEventSignalTimestamp()));
  EXPECT_EQ(GetAcknowledgmentDelayAction(kShortDelay), delegate_.GetActions());
  ASSERT_FALSE(handler_.TriggerPowerButtonAcknowledgmentTimeoutForTesting());
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::UP);
  EXPECT_EQ(kPowerButtonUp, delegate_.GetActions());

  // Check that releasing the power button before it's been acknowledged also
  // stops the timeout.
  AdvanceTime(base::TimeDelta::FromSeconds(1));
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::DOWN);
  EXPECT_EQ(kPowerButtonDown, delegate_.GetActions());
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::UP);
  EXPECT_EQ(kPowerButtonUp, delegate_.GetActions());
  ASSERT_FALSE(handler_.TriggerPowerButtonAcknowledgmentTimeoutForTesting());
  dbus_wrapper_.ClearSentSignals();

  // Let the timeout fire and check that the delegate is notified.
  AdvanceTime(base::TimeDelta::FromSeconds(1));
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::DOWN);
  EXPECT_EQ(kPowerButtonDown, delegate_.GetActions());
  ASSERT_TRUE(handler_.TriggerPowerButtonAcknowledgmentTimeoutForTesting());
  EXPECT_EQ(JoinActions(GetAcknowledgmentDelayAction(kTimeout).c_str(),
                        kMissingPowerButtonAcknowledgment, nullptr),
            delegate_.GetActions());
  ASSERT_FALSE(handler_.TriggerPowerButtonAcknowledgmentTimeoutForTesting());
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::UP);
  EXPECT_EQ(kPowerButtonUp, delegate_.GetActions());

  // Send an acknowledgment with a stale timestamp and check that it doesn't
  // stop the timeout.
  AdvanceTime(base::TimeDelta::FromSeconds(1));
  dbus_wrapper_.ClearSentSignals();
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::DOWN);
  EXPECT_EQ(kPowerButtonDown, delegate_.GetActions());
  CallHandlePowerButtonAcknowledgment(
      base::TimeTicks::FromInternalValue(GetInputEventSignalTimestamp() - 100));
  EXPECT_EQ(kNoActions, delegate_.GetActions());
  ASSERT_TRUE(handler_.TriggerPowerButtonAcknowledgmentTimeoutForTesting());
  EXPECT_EQ(JoinActions(GetAcknowledgmentDelayAction(kTimeout).c_str(),
                        kMissingPowerButtonAcknowledgment, nullptr),
            delegate_.GetActions());
  ASSERT_FALSE(handler_.TriggerPowerButtonAcknowledgmentTimeoutForTesting());
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::UP);
  EXPECT_EQ(kPowerButtonUp, delegate_.GetActions());
}

TEST_F(InputEventHandlerTest, GetSwitchStates) {
  Init();
  input_watcher_.set_tablet_mode(TabletMode::ON);
  input_watcher_.set_lid_state(LidState::OPEN);
  dbus::MethodCall method_call(kPowerManagerInterface, kGetSwitchStatesMethod);
  std::unique_ptr<dbus::Response> response =
      dbus_wrapper_.CallExportedMethodSync(&method_call);
  ASSERT_TRUE(response.get());
  SwitchStates proto;
  ASSERT_TRUE(
      dbus::MessageReader(response.get()).PopArrayOfBytesAsProto(&proto));
  EXPECT_EQ(SwitchStates_TabletMode_ON, proto.tablet_mode());
  EXPECT_EQ(SwitchStates_LidState_OPEN, proto.lid_state());

  input_watcher_.set_tablet_mode(TabletMode::OFF);
  input_watcher_.set_lid_state(LidState::CLOSED);
  response = dbus_wrapper_.CallExportedMethodSync(&method_call);
  ASSERT_TRUE(response.get());
  ASSERT_TRUE(
      dbus::MessageReader(response.get()).PopArrayOfBytesAsProto(&proto));
  EXPECT_EQ(SwitchStates_TabletMode_OFF, proto.tablet_mode());
  EXPECT_EQ(SwitchStates_LidState_CLOSED, proto.lid_state());

  input_watcher_.set_tablet_mode(TabletMode::UNSUPPORTED);
  input_watcher_.set_lid_state(LidState::NOT_PRESENT);
  response = dbus_wrapper_.CallExportedMethodSync(&method_call);
  ASSERT_TRUE(response.get());
  ASSERT_TRUE(
      dbus::MessageReader(response.get()).PopArrayOfBytesAsProto(&proto));
  EXPECT_EQ(SwitchStates_TabletMode_UNSUPPORTED, proto.tablet_mode());
  EXPECT_EQ(SwitchStates_LidState_NOT_PRESENT, proto.lid_state());
}

TEST_F(InputEventHandlerTest, FactoryMode) {
  prefs_.SetInt64(kFactoryModePref, 1);
  Init();

  // Power button events shouldn't be reported to the delegate or announced to
  // Chrome over D-Bus when in factory mode.
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::DOWN);
  input_watcher_.NotifyObserversAboutPowerButtonEvent(ButtonState::UP);
  EXPECT_EQ(kNoActions, delegate_.GetActions());
  EXPECT_EQ(0, dbus_wrapper_.num_sent_signals());

  // Tablet mode and lid events should still be reported, though.
  input_watcher_.set_tablet_mode(TabletMode::ON);
  input_watcher_.NotifyObserversAboutTabletMode();
  EXPECT_EQ(kTabletOn, delegate_.GetActions());
  EXPECT_EQ(InputEvent_Type_TABLET_MODE_ON, GetInputEventSignalType());
  dbus_wrapper_.ClearSentSignals();

  input_watcher_.set_lid_state(LidState::CLOSED);
  input_watcher_.NotifyObserversAboutLidState();
  EXPECT_EQ(kLidClosed, delegate_.GetActions());
  EXPECT_EQ(InputEvent_Type_LID_CLOSED, GetInputEventSignalType());
  dbus_wrapper_.ClearSentSignals();
}

TEST_F(InputEventHandlerTest, OnHoverStateChangeTest) {
  Init();
  input_watcher_.NotifyObserversAboutHoverState(true);
  EXPECT_EQ(kHoverOn, delegate_.GetActions());
  input_watcher_.NotifyObserversAboutHoverState(false);
  EXPECT_EQ(kHoverOff, delegate_.GetActions());
}

}  // namespace policy
}  // namespace power_manager
