1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/wm/user_activity_detector.h"
8 #include "ash/test/ash_test_base.h"
9 #include "ash/wm/user_activity_observer.h"
10 #include "base/compiler_specific.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/time/time.h"
13 #include "ui/aura/test/test_windows.h"
14 #include "ui/aura/window.h"
15 #include "ui/events/event.h"
16 #include "ui/events/event_constants.h"
17 #include "ui/events/keycodes/keyboard_codes.h"
18 #include "ui/gfx/point.h"
22 void SetEventTarget(ui::EventTarget
* target
, ui::Event
* event
) {
23 ui::Event::DispatcherApi
dispatch_helper(event
);
24 dispatch_helper
.set_target(target
);
32 // Implementation that just counts the number of times we've been told that the
34 class TestUserActivityObserver
: public UserActivityObserver
{
36 TestUserActivityObserver() : num_invocations_(0) {}
38 int num_invocations() const { return num_invocations_
; }
39 void reset_stats() { num_invocations_
= 0; }
41 // UserActivityObserver implementation.
42 virtual void OnUserActivity(const ui::Event
* event
) OVERRIDE
{
47 // Number of times that OnUserActivity() has been called.
50 DISALLOW_COPY_AND_ASSIGN(TestUserActivityObserver
);
53 class UserActivityDetectorTest
: public AshTestBase
{
55 UserActivityDetectorTest() {}
56 virtual ~UserActivityDetectorTest() {}
58 virtual void SetUp() OVERRIDE
{
60 observer_
.reset(new TestUserActivityObserver
);
61 detector_
= Shell::GetInstance()->user_activity_detector();
62 detector_
->AddObserver(observer_
.get());
64 now_
= base::TimeTicks::Now();
65 detector_
->set_now_for_test(now_
);
68 virtual void TearDown() OVERRIDE
{
69 detector_
->RemoveObserver(observer_
.get());
70 AshTestBase::TearDown();
74 // Move |detector_|'s idea of the current time forward by |delta|.
75 void AdvanceTime(base::TimeDelta delta
) {
77 detector_
->set_now_for_test(now_
);
80 UserActivityDetector
* detector_
; // not owned
82 scoped_ptr
<TestUserActivityObserver
> observer_
;
87 DISALLOW_COPY_AND_ASSIGN(UserActivityDetectorTest
);
90 // Checks that the observer is notified in response to different types of input
92 TEST_F(UserActivityDetectorTest
, Basic
) {
93 scoped_ptr
<aura::Window
> window(CreateTestWindowInShellWithId(12345));
95 ui::KeyEvent
key_event(ui::ET_KEY_PRESSED
, ui::VKEY_A
, ui::EF_NONE
, false);
96 SetEventTarget(window
.get(), &key_event
);
97 detector_
->OnKeyEvent(&key_event
);
98 EXPECT_FALSE(key_event
.handled());
99 EXPECT_EQ(now_
.ToInternalValue(),
100 detector_
->last_activity_time().ToInternalValue());
101 EXPECT_EQ(1, observer_
->num_invocations());
102 observer_
->reset_stats();
104 base::TimeDelta advance_delta
= base::TimeDelta::FromMilliseconds(
105 UserActivityDetector::kNotifyIntervalMs
);
106 AdvanceTime(advance_delta
);
107 ui::MouseEvent
mouse_event(
108 ui::ET_MOUSE_MOVED
, gfx::Point(), gfx::Point(), ui::EF_NONE
);
109 SetEventTarget(window
.get(), &mouse_event
);
110 detector_
->OnMouseEvent(&mouse_event
);
111 EXPECT_FALSE(mouse_event
.handled());
112 EXPECT_EQ(now_
.ToInternalValue(),
113 detector_
->last_activity_time().ToInternalValue());
114 EXPECT_EQ(1, observer_
->num_invocations());
115 observer_
->reset_stats();
117 base::TimeTicks time_before_ignore
= now_
;
119 // Temporarily ignore mouse events when displays are turned on or off.
120 detector_
->OnDisplayPowerChanging();
121 detector_
->OnMouseEvent(&mouse_event
);
122 EXPECT_FALSE(mouse_event
.handled());
123 EXPECT_EQ(time_before_ignore
.ToInternalValue(),
124 detector_
->last_activity_time().ToInternalValue());
125 EXPECT_EQ(0, observer_
->num_invocations());
126 observer_
->reset_stats();
128 const base::TimeDelta kIgnoreMouseTime
=
129 base::TimeDelta::FromMilliseconds(
130 UserActivityDetector::kDisplayPowerChangeIgnoreMouseMs
);
131 AdvanceTime(kIgnoreMouseTime
/ 2);
132 detector_
->OnMouseEvent(&mouse_event
);
133 EXPECT_FALSE(mouse_event
.handled());
134 EXPECT_EQ(time_before_ignore
.ToInternalValue(),
135 detector_
->last_activity_time().ToInternalValue());
136 EXPECT_EQ(0, observer_
->num_invocations());
137 observer_
->reset_stats();
139 // After enough time has passed, mouse events should be reported again.
140 AdvanceTime(std::max(kIgnoreMouseTime
, advance_delta
));
141 detector_
->OnMouseEvent(&mouse_event
);
142 EXPECT_FALSE(mouse_event
.handled());
143 EXPECT_EQ(now_
.ToInternalValue(),
144 detector_
->last_activity_time().ToInternalValue());
145 EXPECT_EQ(1, observer_
->num_invocations());
146 observer_
->reset_stats();
148 AdvanceTime(advance_delta
);
149 ui::TouchEvent
touch_event(
150 ui::ET_TOUCH_PRESSED
, gfx::Point(), 0, base::TimeDelta());
151 SetEventTarget(window
.get(), &touch_event
);
152 detector_
->OnTouchEvent(&touch_event
);
153 EXPECT_FALSE(touch_event
.handled());
154 EXPECT_EQ(now_
.ToInternalValue(),
155 detector_
->last_activity_time().ToInternalValue());
156 EXPECT_EQ(1, observer_
->num_invocations());
157 observer_
->reset_stats();
159 AdvanceTime(advance_delta
);
160 ui::GestureEvent
gesture_event(
161 ui::ET_GESTURE_TAP
, 0, 0, ui::EF_NONE
,
162 base::TimeDelta::FromMilliseconds(base::Time::Now().ToDoubleT() * 1000),
163 ui::GestureEventDetails(ui::ET_GESTURE_TAP
, 0, 0), 0U);
164 SetEventTarget(window
.get(), &gesture_event
);
165 detector_
->OnGestureEvent(&gesture_event
);
166 EXPECT_FALSE(gesture_event
.handled());
167 EXPECT_EQ(now_
.ToInternalValue(),
168 detector_
->last_activity_time().ToInternalValue());
169 EXPECT_EQ(1, observer_
->num_invocations());
170 observer_
->reset_stats();
173 // Checks that observers aren't notified too frequently.
174 TEST_F(UserActivityDetectorTest
, RateLimitNotifications
) {
175 scoped_ptr
<aura::Window
> window(CreateTestWindowInShellWithId(12345));
177 // The observer should be notified about a key event.
178 ui::KeyEvent
event(ui::ET_KEY_PRESSED
, ui::VKEY_A
, ui::EF_NONE
, false);
179 SetEventTarget(window
.get(), &event
);
180 detector_
->OnKeyEvent(&event
);
181 EXPECT_FALSE(event
.handled());
182 EXPECT_EQ(1, observer_
->num_invocations());
183 observer_
->reset_stats();
185 // It shouldn't be notified if a second event occurs
186 // in the same instant in time.
187 detector_
->OnKeyEvent(&event
);
188 EXPECT_FALSE(event
.handled());
189 EXPECT_EQ(0, observer_
->num_invocations());
190 observer_
->reset_stats();
192 // Advance the time, but not quite enough for another notification to be sent.
194 base::TimeDelta::FromMilliseconds(
195 UserActivityDetector::kNotifyIntervalMs
- 100));
196 detector_
->OnKeyEvent(&event
);
197 EXPECT_FALSE(event
.handled());
198 EXPECT_EQ(0, observer_
->num_invocations());
199 observer_
->reset_stats();
201 // Advance time by the notification interval, definitely moving out of the
202 // rate limit. This should let us trigger another notification.
203 AdvanceTime(base::TimeDelta::FromMilliseconds(
204 UserActivityDetector::kNotifyIntervalMs
));
206 detector_
->OnKeyEvent(&event
);
207 EXPECT_FALSE(event
.handled());
208 EXPECT_EQ(1, observer_
->num_invocations());
211 // Checks that the detector ignores synthetic mouse events.
212 TEST_F(UserActivityDetectorTest
, IgnoreSyntheticMouseEvents
) {
213 scoped_ptr
<aura::Window
> window(CreateTestWindowInShellWithId(12345));
214 ui::MouseEvent
mouse_event(
215 ui::ET_MOUSE_MOVED
, gfx::Point(), gfx::Point(), ui::EF_IS_SYNTHESIZED
);
216 SetEventTarget(window
.get(), &mouse_event
);
217 detector_
->OnMouseEvent(&mouse_event
);
218 EXPECT_FALSE(mouse_event
.handled());
219 EXPECT_EQ(base::TimeTicks().ToInternalValue(),
220 detector_
->last_activity_time().ToInternalValue());
221 EXPECT_EQ(0, observer_
->num_invocations());