Commit 280c46f3 authored by Jia's avatar Jia Committed by Commit Bot

Add user and video activity observers to idle event notifier.

This cl adds ui::UserActivityObserver and
viz::mojom::VideoDetectorObserver to listen to relevant events when
generating idle events.

See https://docs.google.com/document/d/123eFd0rUTu0140V6hJKkkWmpqibdIfM-zTtUR5a2qaQ/edit#
for more detail.

Bug: 784232
Change-Id: I64bae608ea7500406197c3219f26599962256adc
Reviewed-on: https://chromium-review.googlesource.com/780480Reviewed-by: default avatarEmily Stark <estark@chromium.org>
Reviewed-by: default avatarenne <enne@chromium.org>
Reviewed-by: default avatarMichael Giuffrida <michaelpg@chromium.org>
Reviewed-by: default avatarDan Erat <derat@chromium.org>
Reviewed-by: default avatarRenjie Liu <renjieliu@chromium.org>
Commit-Queue: Jia Meng <jiameng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#519864}
parent 1be35973
...@@ -24,6 +24,7 @@ include_rules = [ ...@@ -24,6 +24,7 @@ include_rules = [
"+media/mojo/interfaces", # For platform verification mojom interface. "+media/mojo/interfaces", # For platform verification mojom interface.
"+mojo/edk/embedder", "+mojo/edk/embedder",
"+services/device/public", "+services/device/public",
"+services/viz/public/interfaces",
# Chromeos should not use ozone directly, it must go through mojo as ozone # Chromeos should not use ozone directly, it must go through mojo as ozone
# does not run in process in mus. # does not run in process in mus.
"-ui/ozone/public", "-ui/ozone/public",
......
...@@ -9,20 +9,46 @@ ...@@ -9,20 +9,46 @@
#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/power_manager/idle.pb.h" #include "chromeos/dbus/power_manager/idle.pb.h"
#include "chromeos/dbus/power_manager/suspend.pb.h" #include "chromeos/dbus/power_manager/suspend.pb.h"
#include "ui/base/user_activity/user_activity_detector.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
namespace chromeos { namespace chromeos {
namespace power { namespace power {
namespace ml { namespace ml {
IdleEventNotifier::IdleEventNotifier(const base::TimeDelta& idle_delay) IdleEventNotifier::ActivityData::ActivityData() = default;
: idle_delay_(idle_delay), clock_(std::make_unique<base::DefaultClock>()) { IdleEventNotifier::ActivityData::ActivityData(base::Time last_activity_time,
chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver( base::Time earliest_activity_time)
this); : last_activity_time(last_activity_time),
earliest_activity_time(earliest_activity_time) {}
IdleEventNotifier::ActivityData::ActivityData(const ActivityData& input_data) {
last_activity_time = input_data.last_activity_time;
earliest_activity_time = input_data.earliest_activity_time;
last_user_activity_time = input_data.last_user_activity_time;
last_mouse_time = input_data.last_mouse_time;
last_key_time = input_data.last_key_time;
}
IdleEventNotifier::IdleEventNotifier(
PowerManagerClient* power_client,
viz::mojom::VideoDetectorObserverRequest request)
: clock_(std::make_unique<base::DefaultClock>()),
power_client_(power_client),
binding_(this, std::move(request)) {
DCHECK(power_client_);
power_client_->AddObserver(this);
ui::UserActivityDetector* detector = ui::UserActivityDetector::Get();
DCHECK(detector);
detector->AddObserver(this);
} }
IdleEventNotifier::~IdleEventNotifier() { IdleEventNotifier::~IdleEventNotifier() {
chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver( power_client_->RemoveObserver(this);
this); ui::UserActivityDetector* detector = ui::UserActivityDetector::Get();
DCHECK(detector);
detector->RemoveObserver(this);
} }
void IdleEventNotifier::SetClockForTesting( void IdleEventNotifier::SetClockForTesting(
...@@ -45,7 +71,7 @@ void IdleEventNotifier::LidEventReceived( ...@@ -45,7 +71,7 @@ void IdleEventNotifier::LidEventReceived(
const base::TimeTicks& /* timestamp */) { const base::TimeTicks& /* timestamp */) {
// Ignore lid-close event, as we will observe suspend signal. // Ignore lid-close event, as we will observe suspend signal.
if (state == chromeos::PowerManagerClient::LidState::OPEN) { if (state == chromeos::PowerManagerClient::LidState::OPEN) {
last_activity_time_ = clock_->Now(); UpdateActivityData(ActivityType::USER_OTHER);
ResetIdleDelayTimer(); ResetIdleDelayTimer();
} }
} }
...@@ -54,8 +80,7 @@ void IdleEventNotifier::PowerChanged( ...@@ -54,8 +80,7 @@ void IdleEventNotifier::PowerChanged(
const power_manager::PowerSupplyProperties& proto) { const power_manager::PowerSupplyProperties& proto) {
if (external_power_ != proto.external_power()) { if (external_power_ != proto.external_power()) {
external_power_ = proto.external_power(); external_power_ = proto.external_power();
last_activity_time_ = clock_->Now(); UpdateActivityData(ActivityType::USER_OTHER);
// Power change is a user activity, so reset timer.
ResetIdleDelayTimer(); ResetIdleDelayTimer();
} }
} }
...@@ -63,10 +88,10 @@ void IdleEventNotifier::PowerChanged( ...@@ -63,10 +88,10 @@ void IdleEventNotifier::PowerChanged(
void IdleEventNotifier::SuspendImminent( void IdleEventNotifier::SuspendImminent(
power_manager::SuspendImminent::Reason reason) { power_manager::SuspendImminent::Reason reason) {
if (idle_delay_timer_.IsRunning()) { if (idle_delay_timer_.IsRunning()) {
// This means the user hasn't been idle for more than kModelStartDelaySec. // This means the user hasn't been idle for more than idle_delay. Regardless
// Regardless of the reason of suspend, we won't be emitting any idle event // of the reason of suspend, we won't be emitting any idle event now or
// now or following SuspendDone. // following SuspendDone. We stop the timer to prevent it from resuming in
// We stop the timer to prevent it from resuming in SuspendDone. // SuspendDone.
idle_delay_timer_.Stop(); idle_delay_timer_.Stop();
} }
} }
...@@ -75,20 +100,80 @@ void IdleEventNotifier::SuspendDone(const base::TimeDelta& sleep_duration) { ...@@ -75,20 +100,80 @@ void IdleEventNotifier::SuspendDone(const base::TimeDelta& sleep_duration) {
// TODO(jiameng): consider check sleep_duration to decide whether to log // TODO(jiameng): consider check sleep_duration to decide whether to log
// event. // event.
DCHECK(!idle_delay_timer_.IsRunning()); DCHECK(!idle_delay_timer_.IsRunning());
last_activity_time_ = clock_->Now(); // SuspendDone is triggered by user opening the lid (or other user
// activities).
UpdateActivityData(ActivityType::USER_OTHER);
ResetIdleDelayTimer();
}
void IdleEventNotifier::OnUserActivity(const ui::Event* event) {
if (!event)
return;
// Get the type of activity first then reset timer.
ActivityType type = ActivityType::USER_OTHER;
if (event->IsKeyEvent()) {
type = ActivityType::KEY;
} else if (event->IsMouseEvent() || event->IsTouchEvent()) {
type = ActivityType::MOUSE;
}
UpdateActivityData(type);
ResetIdleDelayTimer();
}
void IdleEventNotifier::OnVideoActivityStarted() {
video_playing_ = true;
UpdateActivityData(ActivityType::VIDEO);
}
void IdleEventNotifier::OnVideoActivityEnded() {
video_playing_ = false;
UpdateActivityData(ActivityType::VIDEO);
ResetIdleDelayTimer(); ResetIdleDelayTimer();
} }
void IdleEventNotifier::ResetIdleDelayTimer() { void IdleEventNotifier::ResetIdleDelayTimer() {
// According to the policy, if there's video playing we should never dim or
// turn off the screen (or transition to any other lower energy state).
if (video_playing_)
return;
idle_delay_timer_.Start(FROM_HERE, idle_delay_, this, idle_delay_timer_.Start(FROM_HERE, idle_delay_, this,
&IdleEventNotifier::OnIdleDelayTimeout); &IdleEventNotifier::OnIdleDelayTimeout);
} }
void IdleEventNotifier::OnIdleDelayTimeout() { void IdleEventNotifier::OnIdleDelayTimeout() {
ActivityData activity_data; if (video_playing_)
activity_data.last_activity_time = last_activity_time_; return;
for (auto& observer : observers_) for (auto& observer : observers_)
observer.OnIdleEventObserved(activity_data); observer.OnIdleEventObserved(data_);
data_ = {};
}
void IdleEventNotifier::UpdateActivityData(ActivityType type) {
base::Time now = clock_->Now();
data_.last_activity_time = now;
if (data_.earliest_activity_time == base::Time()) {
data_.earliest_activity_time = now;
}
if (type == ActivityType::VIDEO)
return;
// All other activity is user-initiated.
data_.last_user_activity_time = now;
switch (type) {
case ActivityType::KEY:
data_.last_key_time = now;
break;
case ActivityType::MOUSE:
data_.last_mouse_time = now;
break;
default:
// We don't track other activity types.
return;
}
} }
} // namespace ml } // namespace ml
......
...@@ -14,6 +14,9 @@ ...@@ -14,6 +14,9 @@
#include "base/timer/timer.h" #include "base/timer/timer.h"
#include "chromeos/dbus/power_manager/power_supply_properties.pb.h" #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
#include "chromeos/dbus/power_manager_client.h" #include "chromeos/dbus/power_manager_client.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/viz/public/interfaces/compositing/video_detector_observer.mojom.h"
#include "ui/base/user_activity/user_activity_observer.h"
namespace base { namespace base {
class Clock; class Clock;
...@@ -27,11 +30,37 @@ namespace ml { ...@@ -27,11 +30,37 @@ namespace ml {
// event is generated. An idle event is generated when the idle period reaches // event is generated. An idle event is generated when the idle period reaches
// |idle_delay_|. No further idle events will be generated until user becomes // |idle_delay_|. No further idle events will be generated until user becomes
// active again, followed by an idle period of |idle_delay_|. // active again, followed by an idle period of |idle_delay_|.
class IdleEventNotifier : public PowerManagerClient::Observer { class IdleEventNotifier : public PowerManagerClient::Observer,
public ui::UserActivityObserver,
public viz::mojom::VideoDetectorObserver {
public: public:
struct ActivityData { struct ActivityData {
// Last activity time. ActivityData();
ActivityData(base::Time last_activity_time,
base::Time earliest_activity_time);
ActivityData(const ActivityData& input_data);
// Last activity time. This is the activity that triggers idle event.
base::Time last_activity_time; base::Time last_activity_time;
// Earliest activity time of a *sequence* of activities: whose idle period
// gap is smaller than |idle_delay_|. This value will be the same as
// |last_activity_time| if the earlier activity happened more than
// |idle_delay_| ago.
base::Time earliest_activity_time;
// Last user activity time of the sequence of activities ending in the last
// activity. It could be different from |last_activity_time| if the last
// activity is not a user activity (e.g. video). It is unset (i.e. 0) if
// there is no user activity before the idle event is fired.
base::Time last_user_activity_time;
// Last mouse/key event time of the sequence of activities ending in the
// last activity. It is unset (i.e. 0) if there is no mouse/key activity
// before the idle event.
base::Time last_mouse_time;
base::Time last_key_time;
}; };
class Observer { class Observer {
...@@ -43,7 +72,8 @@ class IdleEventNotifier : public PowerManagerClient::Observer { ...@@ -43,7 +72,8 @@ class IdleEventNotifier : public PowerManagerClient::Observer {
virtual ~Observer() {} virtual ~Observer() {}
}; };
explicit IdleEventNotifier(const base::TimeDelta& idle_delay); IdleEventNotifier(PowerManagerClient* power_client,
viz::mojom::VideoDetectorObserverRequest request);
~IdleEventNotifier() override; ~IdleEventNotifier() override;
// Set test clock so that we can check activity time. // Set test clock so that we can check activity time.
...@@ -60,6 +90,13 @@ class IdleEventNotifier : public PowerManagerClient::Observer { ...@@ -60,6 +90,13 @@ class IdleEventNotifier : public PowerManagerClient::Observer {
void SuspendImminent(power_manager::SuspendImminent::Reason reason) override; void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
void SuspendDone(const base::TimeDelta& sleep_duration) override; void SuspendDone(const base::TimeDelta& sleep_duration) override;
// ui::UserActivityObserver overrides:
void OnUserActivity(const ui::Event* event) override;
// viz::mojom::VideoDetectorObserver overrides:
void OnVideoActivityStarted() override;
void OnVideoActivityEnded() override;
const base::TimeDelta& idle_delay() const { return idle_delay_; } const base::TimeDelta& idle_delay() const { return idle_delay_; }
void set_idle_delay(const base::TimeDelta& delay) { idle_delay_ = delay; } void set_idle_delay(const base::TimeDelta& delay) { idle_delay_ = delay; }
...@@ -67,26 +104,40 @@ class IdleEventNotifier : public PowerManagerClient::Observer { ...@@ -67,26 +104,40 @@ class IdleEventNotifier : public PowerManagerClient::Observer {
FRIEND_TEST_ALL_PREFIXES(IdleEventNotifierTest, CheckInitialValues); FRIEND_TEST_ALL_PREFIXES(IdleEventNotifierTest, CheckInitialValues);
friend class IdleEventNotifierTest; friend class IdleEventNotifierTest;
enum class ActivityType {
USER_OTHER, // All other user-related activities.
KEY,
MOUSE,
VIDEO,
};
// Resets |idle_delay_timer_|, it's called when a new activity is observed. // Resets |idle_delay_timer_|, it's called when a new activity is observed.
void ResetIdleDelayTimer(); void ResetIdleDelayTimer();
// Called when |idle_delay_timer_| expires. // Called when |idle_delay_timer_| expires.
void OnIdleDelayTimeout(); void OnIdleDelayTimeout();
base::TimeDelta idle_delay_; // Updates all activity-related timestamps.
void UpdateActivityData(ActivityType type);
base::TimeDelta idle_delay_ = base::TimeDelta::FromSeconds(10);
// It is base::DefaultClock, but will be set to a mock clock for tests. // It is base::DefaultClock, but will be set to a mock clock for tests.
std::unique_ptr<base::Clock> clock_; std::unique_ptr<base::Clock> clock_;
base::OneShotTimer idle_delay_timer_; base::OneShotTimer idle_delay_timer_;
PowerManagerClient* power_client_; // not owned.
// Last-received external power state. Changes are treated as user activity. // Last-received external power state. Changes are treated as user activity.
base::Optional<power_manager::PowerSupplyProperties_ExternalPower> base::Optional<power_manager::PowerSupplyProperties_ExternalPower>
external_power_; external_power_;
base::ObserverList<Observer> observers_; base::ObserverList<Observer> observers_;
// Time of last activity, which may be a user or non-user activity (e.g. ActivityData data_;
// video).
base::Time last_activity_time_; // Whether video is playing.
bool video_playing_ = false;
mojo::Binding<viz::mojom::VideoDetectorObserver> binding_;
DISALLOW_COPY_AND_ASSIGN(IdleEventNotifier); DISALLOW_COPY_AND_ASSIGN(IdleEventNotifier);
}; };
......
...@@ -9,11 +9,14 @@ ...@@ -9,11 +9,14 @@
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/test/test_mock_time_task_runner.h" #include "base/test/test_mock_time_task_runner.h"
#include "base/time/clock.h" #include "base/time/clock.h"
#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_power_manager_client.h"
#include "chromeos/dbus/power_manager/idle.pb.h" #include "chromeos/dbus/power_manager/idle.pb.h"
#include "chromeos/dbus/power_manager/power_supply_properties.pb.h" #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
#include "chromeos/dbus/power_manager/suspend.pb.h" #include "chromeos/dbus/power_manager/suspend.pb.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/user_activity/user_activity_detector.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
namespace chromeos { namespace chromeos {
namespace power { namespace power {
...@@ -21,11 +24,13 @@ namespace ml { ...@@ -21,11 +24,13 @@ namespace ml {
namespace { namespace {
// TODO(jiameng): we will add more fields to ActivityData, hence we define an
// equality comparison below for tests.
bool operator==(const IdleEventNotifier::ActivityData& x, bool operator==(const IdleEventNotifier::ActivityData& x,
const IdleEventNotifier::ActivityData& y) { const IdleEventNotifier::ActivityData& y) {
return x.last_activity_time == y.last_activity_time; return x.last_activity_time == y.last_activity_time &&
x.earliest_activity_time == y.earliest_activity_time &&
x.last_user_activity_time == y.last_user_activity_time &&
x.last_mouse_time == y.last_mouse_time &&
x.last_key_time == y.last_key_time;
} }
class TestObserver : public IdleEventNotifier::Observer { class TestObserver : public IdleEventNotifier::Observer {
...@@ -59,9 +64,9 @@ class IdleEventNotifierTest : public testing::Test { ...@@ -59,9 +64,9 @@ class IdleEventNotifierTest : public testing::Test {
: task_runner_(base::MakeRefCounted<base::TestMockTimeTaskRunner>( : task_runner_(base::MakeRefCounted<base::TestMockTimeTaskRunner>(
base::TestMockTimeTaskRunner::Type::kBoundToThread)), base::TestMockTimeTaskRunner::Type::kBoundToThread)),
scoped_context_(task_runner_.get()) { scoped_context_(task_runner_.get()) {
chromeos::DBusThreadManager::Initialize(); viz::mojom::VideoDetectorObserverPtr observer;
idle_event_notifier_ = idle_event_notifier_ = std::make_unique<IdleEventNotifier>(
std::make_unique<IdleEventNotifier>(base::TimeDelta::FromSeconds(1)); &power_client_, mojo::MakeRequest(&observer));
idle_event_notifier_->SetClockForTesting(task_runner_->GetMockClock()); idle_event_notifier_->SetClockForTesting(task_runner_->GetMockClock());
idle_event_notifier_->AddObserver(&test_observer_); idle_event_notifier_->AddObserver(&test_observer_);
ac_power_.set_external_power( ac_power_.set_external_power(
...@@ -71,9 +76,7 @@ class IdleEventNotifierTest : public testing::Test { ...@@ -71,9 +76,7 @@ class IdleEventNotifierTest : public testing::Test {
} }
~IdleEventNotifierTest() override { ~IdleEventNotifierTest() override {
// Destroy idle event notifier before DBusThreadManager is shut down.
idle_event_notifier_.reset(); idle_event_notifier_.reset();
chromeos::DBusThreadManager::Shutdown();
} }
protected: protected:
...@@ -92,6 +95,8 @@ class IdleEventNotifierTest : public testing::Test { ...@@ -92,6 +95,8 @@ class IdleEventNotifierTest : public testing::Test {
std::unique_ptr<IdleEventNotifier> idle_event_notifier_; std::unique_ptr<IdleEventNotifier> idle_event_notifier_;
power_manager::PowerSupplyProperties ac_power_; power_manager::PowerSupplyProperties ac_power_;
power_manager::PowerSupplyProperties disconnected_power_; power_manager::PowerSupplyProperties disconnected_power_;
FakePowerManagerClient power_client_;
ui::UserActivityDetector user_activity_detector_;
private: private:
DISALLOW_COPY_AND_ASSIGN(IdleEventNotifierTest); DISALLOW_COPY_AND_ASSIGN(IdleEventNotifierTest);
...@@ -109,14 +114,15 @@ TEST_F(IdleEventNotifierTest, LidOpenEventReceived) { ...@@ -109,14 +114,15 @@ TEST_F(IdleEventNotifierTest, LidOpenEventReceived) {
base::Time now = task_runner_->Now(); base::Time now = task_runner_->Now();
idle_event_notifier_->LidEventReceived( idle_event_notifier_->LidEventReceived(
chromeos::PowerManagerClient::LidState::OPEN, base::TimeTicks::Now()); chromeos::PowerManagerClient::LidState::OPEN, base::TimeTicks::Now());
FastForwardAndCheckResults(1, {now}); IdleEventNotifier::ActivityData data(now, now);
data.last_user_activity_time = now;
FastForwardAndCheckResults(1, data);
} }
// Lid-closed event will not trigger any future idle event to be generated. // Lid-closed event will not trigger any future idle event to be generated.
TEST_F(IdleEventNotifierTest, LidClosedEventReceived) { TEST_F(IdleEventNotifierTest, LidClosedEventReceived) {
idle_event_notifier_->LidEventReceived( idle_event_notifier_->LidEventReceived(
chromeos::PowerManagerClient::LidState::CLOSED, base::TimeTicks::Now()); chromeos::PowerManagerClient::LidState::CLOSED, base::TimeTicks::Now());
IdleEventNotifier::ActivityData expected_activity_data;
FastForwardAndCheckResults(0, {}); FastForwardAndCheckResults(0, {});
} }
...@@ -126,7 +132,9 @@ TEST_F(IdleEventNotifierTest, LidClosedEventReceived) { ...@@ -126,7 +132,9 @@ TEST_F(IdleEventNotifierTest, LidClosedEventReceived) {
TEST_F(IdleEventNotifierTest, PowerChangedFirstSet) { TEST_F(IdleEventNotifierTest, PowerChangedFirstSet) {
base::Time now = task_runner_->Now(); base::Time now = task_runner_->Now();
idle_event_notifier_->PowerChanged(ac_power_); idle_event_notifier_->PowerChanged(ac_power_);
FastForwardAndCheckResults(1, {now}); IdleEventNotifier::ActivityData data(now, now);
data.last_user_activity_time = now;
FastForwardAndCheckResults(1, data);
} }
// PowerChanged signal is received but source isn't changed, so it won't trigger // PowerChanged signal is received but source isn't changed, so it won't trigger
...@@ -134,9 +142,11 @@ TEST_F(IdleEventNotifierTest, PowerChangedFirstSet) { ...@@ -134,9 +142,11 @@ TEST_F(IdleEventNotifierTest, PowerChangedFirstSet) {
TEST_F(IdleEventNotifierTest, PowerSourceNotChanged) { TEST_F(IdleEventNotifierTest, PowerSourceNotChanged) {
base::Time now = task_runner_->Now(); base::Time now = task_runner_->Now();
idle_event_notifier_->PowerChanged(ac_power_); idle_event_notifier_->PowerChanged(ac_power_);
FastForwardAndCheckResults(1, {now}); IdleEventNotifier::ActivityData data(now, now);
data.last_user_activity_time = now;
FastForwardAndCheckResults(1, data);
idle_event_notifier_->PowerChanged(ac_power_); idle_event_notifier_->PowerChanged(ac_power_);
FastForwardAndCheckResults(1, {now}); FastForwardAndCheckResults(1, data);
} }
// PowerChanged signal is received and source is changed, so it will trigger // PowerChanged signal is received and source is changed, so it will trigger
...@@ -144,11 +154,15 @@ TEST_F(IdleEventNotifierTest, PowerSourceNotChanged) { ...@@ -144,11 +154,15 @@ TEST_F(IdleEventNotifierTest, PowerSourceNotChanged) {
TEST_F(IdleEventNotifierTest, PowerSourceChanged) { TEST_F(IdleEventNotifierTest, PowerSourceChanged) {
base::Time now_1 = task_runner_->Now(); base::Time now_1 = task_runner_->Now();
idle_event_notifier_->PowerChanged(ac_power_); idle_event_notifier_->PowerChanged(ac_power_);
FastForwardAndCheckResults(1, {now_1}); IdleEventNotifier::ActivityData data_1(now_1, now_1);
data_1.last_user_activity_time = now_1;
FastForwardAndCheckResults(1, data_1);
task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(100)); task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(100));
base::Time now_2 = task_runner_->Now(); base::Time now_2 = task_runner_->Now();
idle_event_notifier_->PowerChanged(disconnected_power_); idle_event_notifier_->PowerChanged(disconnected_power_);
FastForwardAndCheckResults(2, {now_2}); IdleEventNotifier::ActivityData data_2(now_2, now_2);
data_2.last_user_activity_time = now_2;
FastForwardAndCheckResults(2, data_2);
} }
// SuspendImminent will not trigger any future idle event. // SuspendImminent will not trigger any future idle event.
...@@ -165,7 +179,105 @@ TEST_F(IdleEventNotifierTest, SuspendImminent) { ...@@ -165,7 +179,105 @@ TEST_F(IdleEventNotifierTest, SuspendImminent) {
TEST_F(IdleEventNotifierTest, SuspendDone) { TEST_F(IdleEventNotifierTest, SuspendDone) {
base::Time now = task_runner_->Now(); base::Time now = task_runner_->Now();
idle_event_notifier_->SuspendDone(base::TimeDelta::FromSeconds(1)); idle_event_notifier_->SuspendDone(base::TimeDelta::FromSeconds(1));
FastForwardAndCheckResults(1, {now}); IdleEventNotifier::ActivityData data(now, now);
data.last_user_activity_time = now;
FastForwardAndCheckResults(1, data);
}
TEST_F(IdleEventNotifierTest, UserActivityKey) {
base::Time now = task_runner_->Now();
ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
idle_event_notifier_->OnUserActivity(&key_event);
IdleEventNotifier::ActivityData data(now, now);
data.last_user_activity_time = now;
data.last_key_time = now;
FastForwardAndCheckResults(1, data);
}
TEST_F(IdleEventNotifierTest, UserActivityMouse) {
base::Time now = task_runner_->Now();
ui::MouseEvent mouse_event(ui::ET_MOUSE_EXITED, gfx::Point(0, 0),
gfx::Point(0, 0), base::TimeTicks(), 0, 0);
idle_event_notifier_->OnUserActivity(&mouse_event);
IdleEventNotifier::ActivityData data(now, now);
data.last_user_activity_time = now;
data.last_mouse_time = now;
FastForwardAndCheckResults(1, data);
}
TEST_F(IdleEventNotifierTest, UserActivityOther) {
base::Time now = task_runner_->Now();
ui::GestureEvent gesture_event(0, 0, 0, base::TimeTicks(),
ui::GestureEventDetails(ui::ET_GESTURE_TAP));
idle_event_notifier_->OnUserActivity(&gesture_event);
IdleEventNotifier::ActivityData data(now, now);
data.last_user_activity_time = now;
FastForwardAndCheckResults(1, data);
}
// Two consecutive activities separated by 2sec only. Only 1 idle event with
// different timestamps for the two activities.
TEST_F(IdleEventNotifierTest, TwoQuickUserActivities) {
base::Time now_1 = task_runner_->Now();
ui::MouseEvent mouse_event(ui::ET_MOUSE_EXITED, gfx::Point(0, 0),
gfx::Point(0, 0), base::TimeTicks(), 0, 0);
idle_event_notifier_->OnUserActivity(&mouse_event);
task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(2));
base::Time now_2 = task_runner_->Now();
ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
idle_event_notifier_->OnUserActivity(&key_event);
IdleEventNotifier::ActivityData data(now_2, now_1);
data.last_user_activity_time = now_2;
data.last_mouse_time = now_1;
data.last_key_time = now_2;
FastForwardAndCheckResults(1, data);
}
TEST_F(IdleEventNotifierTest, ActivityWhileVideoPlaying) {
ui::MouseEvent mouse_event(ui::ET_MOUSE_EXITED, gfx::Point(0, 0),
gfx::Point(0, 0), base::TimeTicks(), 0, 0);
idle_event_notifier_->OnVideoActivityStarted();
idle_event_notifier_->OnUserActivity(&mouse_event);
FastForwardAndCheckResults(0, {});
}
// Activity is observed when video isn't playing, it will start idle timer. But
// before timer expires, video starts playing. So when timer expires, no idle
// event will be generated.
TEST_F(IdleEventNotifierTest, ActivityBeforeVideoStarts) {
ui::MouseEvent mouse_event(ui::ET_MOUSE_EXITED, gfx::Point(0, 0),
gfx::Point(0, 0), base::TimeTicks(), 0, 0);
idle_event_notifier_->OnUserActivity(&mouse_event);
task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(2));
idle_event_notifier_->OnVideoActivityStarted();
FastForwardAndCheckResults(0, {});
}
// An activity is observed when video is playing. No idle timer will be
// triggered but last user activity time will be recorded. Video then stops
// playing that will trigger timer to start.
TEST_F(IdleEventNotifierTest, ActivityAfterVideoStarts) {
ui::MouseEvent mouse_event(ui::ET_MOUSE_EXITED, gfx::Point(0, 0),
gfx::Point(0, 0), base::TimeTicks(), 0, 0);
base::Time now_1 = task_runner_->Now();
idle_event_notifier_->OnVideoActivityStarted();
task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
base::Time now_2 = task_runner_->Now();
idle_event_notifier_->OnUserActivity(&mouse_event);
task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(2));
base::Time now_3 = task_runner_->Now();
idle_event_notifier_->OnVideoActivityEnded();
IdleEventNotifier::ActivityData data(now_3, now_1);
data.last_user_activity_time = now_2;
data.last_mouse_time = now_2;
FastForwardAndCheckResults(1, data);
} }
} // namespace ml } // namespace ml
......
...@@ -31,6 +31,7 @@ class TestingUserActivityLoggerDelegate : public UserActivityLoggerDelegate { ...@@ -31,6 +31,7 @@ class TestingUserActivityLoggerDelegate : public UserActivityLoggerDelegate {
const std::vector<UserActivityEvent>& events() const { return events_; } const std::vector<UserActivityEvent>& events() const { return events_; }
// UserActivityLoggerDelegate overrides:
void LogActivity(const UserActivityEvent& event) override { void LogActivity(const UserActivityEvent& event) override {
events_.push_back(event); events_.push_back(event);
} }
...@@ -44,7 +45,6 @@ class TestingUserActivityLoggerDelegate : public UserActivityLoggerDelegate { ...@@ -44,7 +45,6 @@ class TestingUserActivityLoggerDelegate : public UserActivityLoggerDelegate {
class UserActivityLoggerTest : public testing::Test { class UserActivityLoggerTest : public testing::Test {
public: public:
UserActivityLoggerTest() : activity_logger_(&delegate_) {} UserActivityLoggerTest() : activity_logger_(&delegate_) {}
~UserActivityLoggerTest() override = default; ~UserActivityLoggerTest() override = default;
protected: protected:
...@@ -69,10 +69,11 @@ class UserActivityLoggerTest : public testing::Test { ...@@ -69,10 +69,11 @@ class UserActivityLoggerTest : public testing::Test {
// UserActivityEvent. // UserActivityEvent.
TEST_F(UserActivityLoggerTest, LogAfterIdleEvent) { TEST_F(UserActivityLoggerTest, LogAfterIdleEvent) {
// Trigger an idle event. // Trigger an idle event.
ReportIdleEvent({base::Time::Now()}); base::Time now = base::Time::UnixEpoch();
ReportIdleEvent({now, now});
ReportUserActivity(nullptr); ReportUserActivity(nullptr);
const auto& events = GetEvents(); const std::vector<UserActivityEvent>& events = GetEvents();
ASSERT_EQ(1U, events.size()); ASSERT_EQ(1U, events.size());
UserActivityEvent::Event expected_event; UserActivityEvent::Event expected_event;
...@@ -85,7 +86,8 @@ TEST_F(UserActivityLoggerTest, LogAfterIdleEvent) { ...@@ -85,7 +86,8 @@ TEST_F(UserActivityLoggerTest, LogAfterIdleEvent) {
TEST_F(UserActivityLoggerTest, LogBeforeIdleEvent) { TEST_F(UserActivityLoggerTest, LogBeforeIdleEvent) {
ReportUserActivity(nullptr); ReportUserActivity(nullptr);
// Trigger an idle event. // Trigger an idle event.
ReportIdleEvent({base::Time::Now()}); base::Time now = base::Time::UnixEpoch();
ReportIdleEvent({now, now});
EXPECT_EQ(0U, GetEvents().size()); EXPECT_EQ(0U, GetEvents().size());
} }
...@@ -95,11 +97,12 @@ TEST_F(UserActivityLoggerTest, LogBeforeIdleEvent) { ...@@ -95,11 +97,12 @@ TEST_F(UserActivityLoggerTest, LogBeforeIdleEvent) {
TEST_F(UserActivityLoggerTest, LogSecondEvent) { TEST_F(UserActivityLoggerTest, LogSecondEvent) {
ReportUserActivity(nullptr); ReportUserActivity(nullptr);
// Trigger an idle event. // Trigger an idle event.
ReportIdleEvent({base::Time::Now()}); base::Time now = base::Time::UnixEpoch();
ReportIdleEvent({now, now});
// Another user event. // Another user event.
ReportUserActivity(nullptr); ReportUserActivity(nullptr);
const auto& events = GetEvents(); const std::vector<UserActivityEvent>& events = GetEvents();
ASSERT_EQ(1U, events.size()); ASSERT_EQ(1U, events.size());
UserActivityEvent::Event expected_event; UserActivityEvent::Event expected_event;
...@@ -111,16 +114,18 @@ TEST_F(UserActivityLoggerTest, LogSecondEvent) { ...@@ -111,16 +114,18 @@ TEST_F(UserActivityLoggerTest, LogSecondEvent) {
// Log multiple events. // Log multiple events.
TEST_F(UserActivityLoggerTest, LogMultipleEvents) { TEST_F(UserActivityLoggerTest, LogMultipleEvents) {
// Trigger an idle event. // Trigger an idle event.
ReportIdleEvent({base::Time::Now()}); base::Time now = base::Time::UnixEpoch();
ReportIdleEvent({now, now});
// First user event. // First user event.
ReportUserActivity(nullptr); ReportUserActivity(nullptr);
// Trigger an idle event. // Trigger an idle event.
ReportIdleEvent({base::Time::Now()}); now = base::Time::UnixEpoch();
ReportIdleEvent({now, now});
// Second user event. // Second user event.
ReportUserActivity(nullptr); ReportUserActivity(nullptr);
const auto& events = GetEvents(); const std::vector<UserActivityEvent>& events = GetEvents();
ASSERT_EQ(2U, events.size()); ASSERT_EQ(2U, events.size());
UserActivityEvent::Event expected_event; UserActivityEvent::Event expected_event;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment