• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "ash/wm/user_activity_detector.h"
6 
7 #include "ash/shell.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"
19 
20 namespace {
21 
SetEventTarget(ui::EventTarget * target,ui::Event * event)22 void SetEventTarget(ui::EventTarget* target, ui::Event* event) {
23   ui::Event::DispatcherApi dispatch_helper(event);
24   dispatch_helper.set_target(target);
25 }
26 
27 }
28 
29 namespace ash {
30 namespace test {
31 
32 // Implementation that just counts the number of times we've been told that the
33 // user is active.
34 class TestUserActivityObserver : public UserActivityObserver {
35  public:
TestUserActivityObserver()36   TestUserActivityObserver() : num_invocations_(0) {}
37 
num_invocations() const38   int num_invocations() const { return num_invocations_; }
reset_stats()39   void reset_stats() { num_invocations_ = 0; }
40 
41   // UserActivityObserver implementation.
OnUserActivity(const ui::Event * event)42   virtual void OnUserActivity(const ui::Event* event) OVERRIDE {
43     num_invocations_++;
44   }
45 
46  private:
47   // Number of times that OnUserActivity() has been called.
48   int num_invocations_;
49 
50   DISALLOW_COPY_AND_ASSIGN(TestUserActivityObserver);
51 };
52 
53 class UserActivityDetectorTest : public AshTestBase {
54  public:
UserActivityDetectorTest()55   UserActivityDetectorTest() {}
~UserActivityDetectorTest()56   virtual ~UserActivityDetectorTest() {}
57 
SetUp()58   virtual void SetUp() OVERRIDE {
59     AshTestBase::SetUp();
60     observer_.reset(new TestUserActivityObserver);
61     detector_ = Shell::GetInstance()->user_activity_detector();
62     detector_->AddObserver(observer_.get());
63 
64     now_ = base::TimeTicks::Now();
65     detector_->set_now_for_test(now_);
66   }
67 
TearDown()68   virtual void TearDown() OVERRIDE {
69     detector_->RemoveObserver(observer_.get());
70     AshTestBase::TearDown();
71   }
72 
73  protected:
74   // Move |detector_|'s idea of the current time forward by |delta|.
AdvanceTime(base::TimeDelta delta)75   void AdvanceTime(base::TimeDelta delta) {
76     now_ += delta;
77     detector_->set_now_for_test(now_);
78   }
79 
80   UserActivityDetector* detector_;  // not owned
81 
82   scoped_ptr<TestUserActivityObserver> observer_;
83 
84   base::TimeTicks now_;
85 
86  private:
87   DISALLOW_COPY_AND_ASSIGN(UserActivityDetectorTest);
88 };
89 
90 // Checks that the observer is notified in response to different types of input
91 // events.
TEST_F(UserActivityDetectorTest,Basic)92 TEST_F(UserActivityDetectorTest, Basic) {
93   scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(12345));
94 
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();
103 
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();
116 
117   base::TimeTicks time_before_ignore = now_;
118 
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();
127 
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();
138 
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();
147 
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();
158 
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();
171 }
172 
173 // Checks that observers aren't notified too frequently.
TEST_F(UserActivityDetectorTest,RateLimitNotifications)174 TEST_F(UserActivityDetectorTest, RateLimitNotifications) {
175   scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(12345));
176 
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();
184 
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();
191 
192   // Advance the time, but not quite enough for another notification to be sent.
193   AdvanceTime(
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();
200 
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));
205 
206   detector_->OnKeyEvent(&event);
207   EXPECT_FALSE(event.handled());
208   EXPECT_EQ(1, observer_->num_invocations());
209 }
210 
211 // Checks that the detector ignores synthetic mouse events.
TEST_F(UserActivityDetectorTest,IgnoreSyntheticMouseEvents)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());
222 }
223 
224 }  // namespace test
225 }  // namespace ash
226